| 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 go to 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:
| 〈go to statement⟩ | \(\longrightarrow \) | go to 〈label⟩\(\ \mid \ \)goto 〈label⟩ |
| 〈label⟩ | \(\longrightarrow \) | 〈identifier⟩ |
| 〈labeled statement⟩ | \(\longrightarrow \) | 〈label⟩:〈statement⟩ |
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.
return can be used on the top level inside the compound statement, i.e. as
one of the statements bracketed together by the begin… end
return can be used within a top level << … >> construction within the
compound statement. In this case, the return transfers control out of both
the group statement and the compound statement.
return can be used within an if… then… else… on the top level within
the compound statement.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 |