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