Most of the standard procedures that are built-in to Modula-2 have already arisen in the course of various examples thus far in the text. The purpose of this section is to provide a summary in one place of all the standard procedures, together with a few examples of code utilizing them.
(i) ABS (number) returns the "absolute value" of "number".
The absolute value of a number is its distance from zero, without regard to direction. More technically, it is the square root of the square of a number.
Either way one looks at it:
ABS (5) = 5 ABS (-10) = 10 ABS (2.7) = 2.7 ABS (-3.51) = 3.51
The actual parameter type and the result type must either be both INTEGER or both REAL. There is a little magic in this, in that no user-defined procedure can take or return more than one type, even through the built-in function procedure may do so. If one had firstInt and secondInt of type INTEGER and firstReal and secondReal of type REAL, the following would be valid:
firstInt := ABS (secondInt); firstReal := ABS (secondReal); firstInt := TRUNC (ABS (secondReal)); firstReal := FLOAT (ABS (secondInt));
Recall that there is a potential problem with loops that fail to terminate or comparisons that fail to yield equality because a REAL might never be identically equal to zero. ABS allows this to be avoided by writing, say:
REPEAT statement sequence; UNTIL ABS (realVar) < epsilon; (* set to a small number, say .0000001 *)
The loop terminates when the realVar becomes sufficiently close to zero.
(ii) CHR (number) returns the character whose associated numerical value is the CARDINAL number. This number is sequential number of the character, in the underlying national character set (often ISO/ASCII.)
If one wrote the assignment ch := CHR (65) then ch would be equal to A
(iii) DEC (s) and INC (s)--subtract or add one (respectively) to the scalar s.
(iv) DEC (s, number), INC (s, number)--subtract number or add number (respectively) to the scalar s.
VAR num : CARDINAL; ch : CHAR; BEGIN num := 1; DEC (num); (* it's now zero *) INC (num, 8); (* now it's eight *) ch := "Z"; INC (ch); (* holds next char after "Z" *) INC (num, num-1) (* now it's 15 *) (* INC allows expressions for the increment *)
Care must be taken not to INC or DEC a variable beyond its defined limits. For instance, if num were zero, then DEC (num) would leave num undefined. As noted, the increment or decrement need not be a literal; it can be any expression that evaluates to a number compatible with the type of variable being used. INC (ch, b-a) is allowed, provided b-a is a suitable INTEGER. This in turn means that it is correct to INC or DEC by a negative number.
NOTES: 1. When there is a choice between x := x + 1 and INC (x), always use the latter, as in most systems the code generated executes more quickly. The same applies to DEC.
2. The two versions each of INC and DEC are the only regular procedures described in this section. The others are all function procedures.
(v) CAP (ch) converts the contents of the CHAR variable to uppercase.
If ch, ck are both of type CHAR then:
ch := 'a' (* or, ch := 'A' *) ck := CAP (ch) would leave ck holding the value 'A'.
This was used to avoid writing:
IF (ch = 'Y') OR (ch = 'y').
WriteString ("Are you sure you want to do this? "); WriteLn; WriteString ("Answer Y or N ===> "); Read (ans); IF CAP (ans) = 'Y' THEN Execute (Program) ELSE Execute (User) END;
(vi) FLOAT (n) and LFLOAT (n) convert any real, integer, or cardinal into the type REAL or LONGREAL, respectively. Thus:
realVar := FLOAT (5); (* produces 5.0 *) lrealVar := LFLOAT (realVar); (* produces longreal 5.0 *) lrealVar := LFLOAT (-10); (* produces -10.0 in longreal format *)
(vii) ODD (n) is a BOOLEAN function that returns TRUE if the INTEGER or CARDINAL expression n is odd and FALSE if it is even.
VAR flag : BOOLEAN number : CARDINAL BEGIN number := 5; flag := ODD (number); (* flag is now true *) INC (number); (* flag is still true; it has not been re-evaluated *) flag := ODD (number); (* flag is now false *)
Here is a section of code that raises the quantity (-1) to the power exponent and places the result in the variable answer.
PROCEDURE PowerOfOne (theExponent : INTEGER) : INTEGER; BEGIN IF ODD (exponent) THEN RETURN -1 ELSE RETURN 1 END; END PowerOfOne;
(viii) MAX (type) and MIN (type) take as a parameter the name of any scalar type (including REAL) and return the maximum and minimum values possible for items of that type (respectively). MAX and MIN are most useful, for example, when applied just before attempting to TRUNC a REAL. Assume that integerNum is INTEGER and realNum is REAL.
IF (realNum > 0) AND (realNum < FLOAT (MAX (INTEGER)) ) THEN integerNum := TRUNC (realNum) ELSE ErrorRoutine END
(ix) TRUNC(num) and INT(num) will convert the supplied numeric parameter to a cardinal or integer value, respectively, with truncation as needed. Thus:
TRUNC (ABS(-7.245)); (* produces 7 *) TRUNC (8.1); (* produces 8 *) INT (2.3); (* produces 2 *) INT (-4.78); (* produces -4 *)