1\chapter{Procedures}\ttindextype{PROCEDURE}{command}
2\hypertarget{command:PROCEDURE}{}
3
4It is often useful to name a statement for repeated use in calculations
5with varying parameters, or to define a complete evaluation procedure for
6an operator. {\REDUCE} offers a procedural declaration for this purpose. Its
7general syntax is:
8\begin{syntax}
9  [\meta{procedural type}]\texttt{ PROCEDURE }\meta{name}[\meta{varlist}]\texttt{;}
10    \meta{statement}\texttt{;}
11\end{syntax}
12where
13\begin{syntax}
14  \meta{varlist}\ \BNFprod\ \texttt{(}\meta{variable}\texttt{,}\,\dots\texttt{,}\,\meta{variable}\texttt{)}
15\end{syntax}
16This will be explained more fully in the following sections.
17
18In the algebraic mode of {\REDUCE} the \meta{procedural type} can be
19omitted, since the default is \texttt{ALGEBRAIC}.  Procedures of type
20\texttt{INTEGER} or \texttt{REAL} may also be used.  In the former case, the system
21checks that the value of the procedure is an integer.  At present, such
22checking is not done for a real procedure, although this will change in
23the future when a more complete type checking mechanism is installed.
24Users should therefore only use these types when appropriate.  An empty
25variable list may also be omitted.
26
27All user-defined procedures are automatically declared to be operators.
28
29In order to allow users relatively easy access to the whole {\REDUCE} source
30program, system procedures are not protected against user redefinition. If
31a procedure is redefined, a message
32\begin{verbatim}
33        *** <procedure name> REDEFINED
34\end{verbatim}
35is printed. If this occurs, and the user is not redefining his own
36procedure, he is well advised to rename it, and possibly start over
37(because he has {\em already\/} redefined some internal procedure whose correct
38functioning may be required for his job!)
39
40All required procedures should be defined at the top level, since they
41have global scope throughout a program. In particular, an attempt to
42define a procedure within a procedure will cause an error to occur.
43
44\section{Procedure Heading}\index{Procedure!heading}
45
46Each procedure has a heading consisting of the word \texttt{PROCEDURE}
47(optionally preceded by the word \texttt{ALGEBRAIC}), followed by the name of
48the procedure to be defined, and followed by its formal parameters -- the
49symbols that will be used in the body of the definition to illustrate
50what is to be done.  There are three cases:
51\begin{enumerate}
52\item No parameters. Simply follow the procedure name with a terminator
53(semicolon or dollar sign).
54\begin{verbatim}
55        procedure abc;
56\end{verbatim}
57
58When such a procedure is used in an expression or command, \texttt{abc()}, with
59empty parentheses, must be written.
60
61\item One parameter.  Enclose it in parentheses \emph{or} just leave at
62least one space, then follow with a terminator.
63\begin{verbatim}
64        procedure abc(x);
65\end{verbatim}
66or
67\begin{verbatim}
68        procedure abc x;
69\end{verbatim}
70
71\item More than one parameter. Enclose them in parentheses, separated by
72commas, then follow with a terminator.
73\begin{verbatim}
74        procedure abc(x,y,z);
75\end{verbatim}
76\end{enumerate}
77Referring to the last example, if later in some expression being evaluated
78the symbols \texttt{abc(u,p*q,123)} appear, the operations of the procedure
79body will be carried out as if \texttt{X} had the same value as \texttt{U} does,
80\texttt{Y} the same value as \texttt{p*q} does, and \texttt{Z} the value 123.  The
81values of \texttt{X}, \texttt{Y}, \texttt{Z}, after the procedure body operations
82are completed are unchanged.  So, normally, are the values of \texttt{U},
83\texttt{P}, \texttt{Q}, and (of course) 123. (This is technically referred to as
84call by value.)\index{Call by value}
85
86The reader will have noted the word \emph{normally} a few lines earlier. The
87call by value protections can be bypassed if necessary, as described
88elsewhere.
89
90\section{Procedure Body}\index{Procedure!body}
91
92Following the delimiter that ends the procedure heading must be a
93\emph{single} statement defining the action to be performed or the value to be
94delivered.  A terminator must follow the statement.  If it is a semicolon,
95the name of the procedure just defined is printed.  It is not printed if a
96dollar sign is used.
97
98If the result wanted is given by a formula of some kind, the body is just
99that formula, using the variables in the procedure heading.
100
101\textit{Simple Example:}
102
103If \texttt{f(x)} is to mean \texttt{(x+5)*(x+6)/(x+7)}, the entire procedure
104definition could read
105\begin{verbatim}
106        procedure f x; (x+5)*(x+6)/(x+7);
107\end{verbatim}
108Then \texttt{f(10)} would evaluate to 240/17, \texttt{f(a-6)} to
109\texttt{A*(A-1)/(A+1)}, and so on.
110
111\textit{More Complicated Example:}
112
113Suppose we need a function \texttt{p(n,x)} that, for any positive integer
114\texttt{N}, is the Legendre polynomial\index{Legendre polynomials} of order
115$n$. We can define this operator using the
116textbook formula defining these functions:
117\[
118p_n(x) = \left.\frac{1}{n!}\
119\frac{{d}^n}{dy^n}\ \frac{1}{{(y^2 - 2xy + 1)}^{\frac{1}{2}}}\right\vert_{y=0}
120\]
121Put into words, the Legendre polynomial $p_n(x)$ is the result of
122substituting $y=0$ in the $n^{th}$ partial derivative with respect to $y$
123of a certain fraction involving $x$ and $y$, then dividing that by $n!$.
124
125This verbal formula can easily be written in {\REDUCE}:
126\begin{verbatim}
127        procedure p(n,x);
128           sub(y=0,df(1/(y^2-2*x*y+1)^(1/2),y,n))
129               /(for i:=1:n product i);
130\end{verbatim}
131Having input this definition, the expression evaluation
132\begin{verbatim}
133        2p(2,w);
134\end{verbatim}
135would result in the output
136\begin{verbatim}
137           2
138        3*W  - 1 .
139\end{verbatim}
140If the desired process is best described as a series of steps, then a group
141or compound statement can be used.
142%\extendedmanual{\newpage}
143
144\textit{Example:}
145
146The above Legendre polynomial example can be rewritten as a series of steps
147instead of a single formula as follows:
148\begin{verbatim}
149        procedure p(n,x);
150          begin scalar seed,deriv,top,fact;
151               seed:=1/(y^2 - 2*x*y +1)^(1/2);
152               deriv:=df(seed,y,n);
153               top:=sub(y=0,deriv);
154               fact:=for i:=1:n product i;
155               return top/fact
156          end;
157\end{verbatim}
158Procedures may also be defined recursively.  In other words, the procedure
159body\index{Procedure!body} can include references to the procedure name
160itself, or to other procedures that themselves reference the given
161procedure.  As an example, we can define the Legendre polynomial through
162its standard recurrence relation:
163\begin{verbatim}
164        procedure p(n,x);
165           if n<0 then rederr "Invalid argument to P(N,X)"
166            else if n=0 then 1
167            else if n=1 then x
168            else ((2*n-1)*x*p(n-1,x)-(n-1)*p(n-2,x))/n;
169\end{verbatim}
170
171\hypertarget{operator:REDERR}{}
172The operator \texttt{REDERR}\ttindex{REDERR} in the above example provides
173for a simple error exit from an algebraic procedure (and also a block).
174It can take a string as argument.
175
176It should be noted however that all the above definitions of \texttt{p(n,x)} are
177quite inefficient if extensive use is to be made of such polynomials, since
178each call effectively recomputes all lower order polynomials. It would be
179better to store these expressions in an array, and then use say the
180recurrence relation to compute only those polynomials that have not already
181been derived. We leave it as an exercise for the reader to write such a
182definition.
183
184\section{Matrix-valued Procedures}
185\ttindex{MATRIXPROC}
186\hypertarget{command:MATRIXPROC}{}
187
188Normally, procedures can only return scalar values. In order for a procedure to
189return a matrix, it has to be declared of
190type \k{MATRIXPROC}:\index{Procedure!matrix-valued}
191\begin{verbatim}
192        matrixproc SkewSym1 (w);
193           mat((0,-w(3,1),w(2,1)),
194               (w(3,1),0,-w(1,1)),
195               (-w(2,1), w(1,1), 0));
196\end{verbatim}
197Following this declaration, the call to \texttt{SkewSym1} can be used as a matrix, e.g.
198\begin{verbatim}
199        X := SkewSym1(mat((qx),(qy),(qz)));
200
201
202             [  0     - qz   qy  ]
203             [                   ]
204        x := [ qz      0     - qx]
205             [                   ]
206             [ - qy   qx      0  ]
207
208        X * mat((rx),(ry),(rz));
209
210
211        [ qy*rz - qz*ry  ]
212        [                ]
213        [ - qx*rz + qz*rx]
214        [                ]
215        [ qx*ry - qy*rx  ]
216\end{verbatim}
217
218
219\section{Using LET Inside Procedures}
220
221By using \texttt{LET}\ttindex{LET} instead of an assignment in the procedure
222body\index{Procedure!using \texttt{LET} inside body} it is possible to bypass the call-by-value
223\index{Call by value} protection.  If \texttt{X} is a formal parameter or local
224variable of the procedure (i.e. is in the heading or in a local
225declaration), and \texttt{LET} is used instead of \texttt{:=} to make an
226assignment to \texttt{X}, e.g.
227
228\begin{verbatim}
229        let x = 123;
230\end{verbatim}
231then it is the variable that is the value of \texttt{X} that is changed.
232This effect also occurs with local variables defined in a block.  If the
233value of \texttt{X} is not a variable, but a more general expression, then it
234is that expression that is used on the left-hand side of the \texttt{LET}
235statement.  For example, if \texttt{X} had the value \texttt{p*q}, it is as if
236\texttt{let p*q = 123} had been executed.
237
238\section{LET Rules as Procedures}
239
240The \texttt{LET}\ttindex{LET} statement offers an alternative syntax and
241semantics for procedure definition.
242
243In place of
244\begin{verbatim}
245        procedure abc(x,y,z); <procedure body>;
246\end{verbatim}
247one can write
248\begin{verbatim}
249        for all x,y,z let abc(x,y,z) = <procedure body>;
250\end{verbatim}
251There are several differences to note.
252
253If the procedure body contains an assignment to one of the formal
254parameters, e.g.
255\begin{verbatim}
256        x := 123;
257\end{verbatim}
258in the \texttt{PROCEDURE} case it is a variable holding a copy of the first
259actual argument that is changed.  The actual argument is not changed.
260
261In the \texttt{LET} case, the actual argument is changed.  Thus, if \texttt{ABC}
262is defined using \texttt{LET}, and \texttt{abc(u,v,w)} is evaluated, the value
263of \texttt{U} changes to 123.  That is, the \texttt{LET} form of definition
264allows the user to bypass the protections that are enforced by the call
265by value conventions of standard \texttt{PROCEDURE} definitions.
266
267\textit{Example:}  We take our earlier \texttt{FACTORIAL}\ttindex{FACTORIAL}
268procedure and write it as a \texttt{LET} statement.
269\begin{verbatim}
270        for all n let factorial n =
271                    begin scalar m,s;
272                    m:=1; s:=n;
273                l1: if s=0 then return m;
274                    m:=m*s;
275                    s:=s-1;
276                    go to l1
277                end;
278\end{verbatim}
279The reader will notice that we introduced a new local variable, \texttt{S},
280and set it equal to \texttt{N}.  The original form of the procedure contained
281the statement \texttt{n:=n-1;}.  If the user asked for the value of {\tt
282factorial(5)} then \texttt{N} would correspond to, not just have the value
283of, 5, and {\REDUCE} would object to trying to execute the statement
2845 := $5-1$.
285
286If \texttt{PQR} is a procedure with no parameters,
287\begin{verbatim}
288        procedure pqr;
289           <procedure body>;
290\end{verbatim}
291it can be written as a \texttt{LET} statement quite simply:
292\begin{verbatim}
293        let pqr = <procedure body>;
294\end{verbatim}
295To call \emph{procedure} \texttt{PQR}, if defined in the latter form, the empty
296parentheses would not be used: use \texttt{PQR} not \texttt{PQR()} where a call
297on the procedure is needed.
298
299The two notations for a procedure with no arguments can be combined. \texttt{PQR}
300can be defined in the standard \texttt{PROCEDURE} form. Then a \texttt{LET}
301statement
302\begin{verbatim}
303        let pqr = pqr();
304\end{verbatim}
305would allow a user to use \texttt{PQR} instead of \texttt{PQR()} in calling the
306procedure.
307
308A feature available with \texttt{LET}-defined procedures and not with procedures
309defined in the standard way is the possibility of defining partial
310functions.\index{Function}
311\begin{verbatim}
312    for all x such that numberp x let uvw(x)=<procedure body>;
313\end{verbatim}
314Now \texttt{UVW} of an integer would be calculated as prescribed by the procedure
315body, while \texttt{UVW} of a general argument, such as \texttt{Z} or \texttt{p+q}
316(assuming these evaluate to themselves) would simply stay \texttt{uvw(z)}
317or \texttt{uvw(p+q)} as the case may be.
318
319
320\section{REMEMBER Statement}\ttindex{REMEMBER}
321\hypertarget{command:REMEMBER}{}
322
323Setting the remember option for an algebraic procedure by
324\begin{verbatim}
325     REMEMBER (PROCNAME:procedure);
326\end{verbatim}
327saves all intermediate results of such procedure evaluations, including
328recursive calls.  Subsequent calls to the procedure can then be determined
329from the saved results, and thus the number of evaluations (or the
330complexity) can be reduced.  This mode of evalation costs extra memory, of
331course.  In addition, the procedure must be free of side--effects.
332
333The following examples show the effect of the remember statement
334on two well--known examples.
335
336\begin{samepage}
337\begin{verbatim}
338procedure H(n);      % Hofstadter's function
339 if numberp n then
340 << cnn := cnn +1;   % counts the calls
341 if n < 3 then 1 else H(n-H(n-1))+H(n-H(n-2))>>;
342
343remember h;
344
345<< cnn := 0; H(100); cnn>>;
346
347100
348
349% H has been called 100 times only.
350
351procedure A(m,n);    % Ackermann function
352
353 if m=0 then n+1 else
354  if n=0 then A(m-1,1) else
355  A(m-1,A(m,n-1));
356
357remember a;
358
359A(3,3);
360
361\end{verbatim}
362\end{samepage}
363