|
So far we have only discussed function expressions, these being a
mechanism for computing new values from the values of identifiers in
the current context. Together with assignment this provides us with a
means of changing the current context -- to compute a new value for an
identifier in the current context, we call a function and then
re-assign the identifier with the result of this function. That is
we do
> X := f(Y);
where Y is a list of arguments possibly including the current value of
X.
At times however using re-assignment to change the value associated with
an identifier can be both un-natural and inefficient. Take the problem
of computing some reduced form of a matrix. We could write a function
that looked something like this,
reduce :=
function( m )
local lm;
...
lm := m;
while not reduced do
...
lm := some_reduction(m);
...
end while;
...
end function;
Note that the local lm is necessary since we cannot assign to the
function's formal argument m since it stands for a value (and
values cannot be assigned to). Note also that the function is inefficient
in its space usage since at any
given point in the program there are at least two different copies of the
matrix (if the function was recursive then there would be more than two
copies!).
Finally the function is also un-natural. It
is perhaps more natural to think of writing a program that takes a given
matrix and changes that matrix into its reduced form (i.e., the original
matrix is lost). To accommodate for this style of programming, Magma
includes a mechanism, the procedure expression with its reference
arguments, for changing an association of an identifier and a value
in place.
Before examining procedure expressions further, it is useful to
look at a simple example of a procedure expression. Say we type:
> a := 5; b := 6;
giving the context [ (a,5), (b,6) ]. Say we now type the following:
> p := procedure( x, ~y ) y := x; end procedure;
This gives us a context that looks like [ (a,5), (b,6),
(p, PROC(x,~y : y := x;)) ], using a notation analogous to the FUNC
notation.
Say we now type the following statement,
> p(a, ~b);
This is known as a call of the procedure p (strictly it should be
known as a call to the procedure value associated with the identifier
p, since like functions, procedures in Magma are first class values!).
Its effect is to change the current context to [ (a,5), (b,5),
(p, PROC(a,~b : b := a;)) ]. a and x are called actual and formal value
arguments respectively since they are not prefixed by a ~, while b and y
are called actual and formal reference arguments
respectively because they
are prefixed by a ~.
This example illustrates the defining attribute of procedures, namely that
rather than returning a value, a procedure changes the context in which
it is called. In this case the value of b was changed by the call to p.
Observe however that only b was changed by the call to p as only
b in the call, and its corresponding formal argument y in the definition,
are reference arguments (i.e., prefixed with a ~).
A procedure may therefore
only change that part of the context associated with its reference arguments!
All other parts of the context are left unchanged. In this case a and p
were left unchanged!
Note that apart from reference arguments (and the corresponding fact that
that procedures do not return values), procedures are exactly like
functions. In particular:
- a)
- procedures are first class values that can be assigned to identifiers, passed as arguments, returned from functions, etc.
- b)
- procedure expressions are evaluated in the same way that function
expressions are.
- c)
- procedure value arguments (both formal and actual) behave exactly like
function arguments (both formal and actual). Thus procedure value arguments
obey the standard substitution semantics.
- d)
- procedures employ the same notion of scope as functions.
- e)
- procedure calling behaves like function application.
- f)
- procedures may be declared `forward' to allow for (mutual) recursion.
- g)
- a procedure may be assigned to an identifier in the initial context.
The remainder of this section will thus restrict itself to looking at
reference arguments, the point of difference between procedures and
functions.
[Next][Prev] [Right] [Left] [Up] [Index] [Root]
|