Up | Prev | PrevTail | Tail |
Often the desired process can best (or only) be described as a series of steps to be carried out one after the other. In many cases, this can be achieved by use of the group statement. However, each step often provides some intermediate result, until at the end we have the final result wanted. Alternatively, iterations on the steps are needed that are not possible with constructs such as while or repeat statements. In such cases the steps of the process must be enclosed between the words begin and end forming what is technically called a block or compound statement. Such a compound statement can in fact be used wherever a group statement appears. The converse is not true: begin …end can be used in ways that <<… >> cannot.
If intermediate results must be formed, local variables must be provided in which to store them. Local means that their values are deleted as soon as the block’s operations are complete, and there is no conflict with variables outside the block that happen to have the same name. Local variables are created by a scalar declaration immediately after the begin:
scalar a,b,c,z;
If more convenient, several scalar declarations can be given one after another:
scalar a,b,c; scalar z;
In place of scalar one can also use the declarations integer or real. In the present version of REDUCE variables declared integer are expected to have only integer values, and are initialized by default to 0. real variables on the other hand are currently treated as algebraic mode scalars.
CAUTION: integer, real and scalar declarations can only be given immediately after a begin. An error will result if they are used after other statements in a block (including array and operator declarations, which are global in scope), or outside the top-most block (e.g., at the top level). All variables declared scalar are automatically initialized by default to zero in algebraic mode (nil in symbolic mode).
Optionally, each variable appearing in a scalar, integer or real declaration can be followed by an assignment operator and an initial value, which overrides the default initial value. For example,
scalar x := 5;
has the same effect as
scalar x; x := 5;
Any symbols not declared as local variables in a block refer to the variables of the same name in the current calling environment. In particular, if they are not so declared at a higher level (e.g., in a surrounding block or as parameters in a calling procedure), their values can be permanently changed.
Following the scalar declaration(s), if any, write the statements to be executed, one after the other, separated by delimiters (e.g., ; or $) (it doesn’t matter which). However, from a stylistic point of view, ; is preferred.
The last statement in the body, just before end, need not have a terminator (since the begin… end are in a sense brackets confining the block statements). The last statement must also be the command return followed by the variable or expression whose value is to be the value returned by the procedure. If the return is omitted (or nothing is written after the word return) the procedure will have no value or the value zero, depending on how it is used (and nil in symbolic mode). Remember to put a terminator after the end.
Examples:
Given a previously assigned integer value for n, the following block will compute the Legendre polynomial of degree n in the variable x:
begin scalar seed,deriv,top,fact; seed:=1/(y^2 - 2*x*y +1)^(1/2); deriv:=df(seed,y,n); top:=sub(y=0,deriv); fact:=for i:=1:n product i; return top/fact end;
This block uses explicit initialization and computes the 10th Fibonacci number:
begin integer f1 := 1, f2 := 1, f3; for i := 3 : 10 do << f3 := f1 + f2; f1 := f2; f2 := f3 >>; return f3 end;
It is possible to have more complicated structures inside the begin… end brackets than indicated in the previous example. That the individual lines of the program need not be assignment statements, but could be almost any other kind of statement or command, needs no explanation. For example, conditional statements, and while and repeat constructions, have an obvious role in defining more intricate blocks.
If these structured constructs don’t suffice, it is possible to use labels and go tos within a compound statement, and also to use return in places within the block other than just before the end. The following subsections discuss these matters in detail. For many readers the following example, presenting one possible definition of a process to calculate the factorial of n for preassigned n will suffice:
Example:
begin scalar m; m:=1; l: if n=0 then return m; m:=m*n; n:=n-1; go to l end;
Within a begin …end compound statement it is possible to label statements, and transfer to them out of sequence using goto statements. Only statements on the top level inside compound statements can be labeled, not ones inside subsidiary constructions like \(<<\) …\(>>\), if…then…, while…do…, etc.
Labels and go to statements have the syntax:
\(\langle \)go to statement\(\rangle \) | \(\longrightarrow \) | go to \(\langle \)label\(\rangle \)\(\ \mid \ \)goto \(\langle \)label\(\rangle \) |
\(\langle \)label\(\rangle \) | \(\longrightarrow \) | \(\langle \)identifier\(\rangle \) |
\(\langle \)labeled statement\(\rangle \) | \(\longrightarrow \) | \(\langle \)label\(\rangle \):\(\langle \)statement\(\rangle \) |
Note that statement names cannot be used as labels.
While go to is an unconditional transfer, it is frequently used in conditional statements such as
if x>5 then go to abcd;
giving the effect of a conditional transfer.
Transfers using go tos can only occur within the block in which the go to is used. In other words, you cannot transfer from an inner block to an outer block using a go to. However, if a group statement occurs within a compound statement, it is possible to jump out of that group statement to a point within the compound statement using a go to.
The value corresponding to a begin… end compound statement, such as a procedure body, is normally 0 (nil in symbolic mode). By executing a return statement in the compound statement a different value can be returned. After a return statement is executed, no further statements within the compound statement are executed.
Examples:
return x+y; return m; return;
Note that parentheses are not required around the x+y, although they are permitted. The last example is equivalent to return 0 or return nil, depending on whether the block is used as part of an expression or not.
Since return actually moves up only one block level, in a sense the casual user is not expected to understand, we tabulate some cautions concerning its use.
NOTE: At present, there is no construct provided to permit early termination of a for, while, or repeat statement. In particular, the use of return in such cases results in a syntax error. For example,
begin scalar y; y := for i:=0:99 do if a(i)=x then return b(i); ...
will lead to an error.
Up | Prev | PrevTail | Front |