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 scalar
s.
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
to
s 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:
\(\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 to
s 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 |