proc.tex 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. \chapter{Procedures}\ttindex{PROCEDURE}
  2. It is often useful to name a statement for repeated use in calculations
  3. with varying parameters, or to define a complete evaluation procedure for
  4. an operator. {\REDUCE} offers a procedural declaration for this purpose. Its
  5. general syntax is:
  6. \begin{verbatim}
  7. [<procedural type>] PROCEDURE <name>[<varlist>];<statement>;
  8. \end{verbatim}
  9. where
  10. \begin{verbatim}
  11. <varlist> ::= (<variable>,...,<variable>)
  12. \end{verbatim}
  13. This will be explained more fully in the following sections.
  14. In the algebraic mode of {\REDUCE} the {\tt <procedure type>} can be
  15. omitted, since the default is {\tt ALGEBRAIC}. Procedures of type {\tt
  16. INTEGER} or {\tt REAL} may also be used. In the former case, the system
  17. checks that the value of the procedure is an integer. At present, such
  18. checking is not done for a real procedure, although this will change in
  19. the future when a more complete type checking mechanism is installed.
  20. Users should therefore only use these types when appropriate. An empty
  21. variable list may also be omitted.
  22. All user-defined procedures are automatically declared to be operators.
  23. In order to allow users relatively easy access to the whole {\REDUCE} source
  24. program, system procedures are not protected against user redefinition. If
  25. a procedure is redefined, a message
  26. \begin{verbatim}
  27. *** <procedure name> REDEFINED
  28. \end{verbatim}
  29. is printed. If this occurs, and the user is not redefining his own
  30. procedure, he is well advised to rename it, and possibly start over
  31. (because he has {\em already\/} redefined some internal procedure whose correct
  32. functioning may be required for his job!)
  33. All required procedures should be defined at the top level, since they
  34. have global scope throughout a program. In particular, an attempt to
  35. define a procedure within a procedure will cause an error to occur.
  36. \section{Procedure Heading}\index{Procedure heading}
  37. Each procedure has a heading consisting of the word {\tt PROCEDURE}
  38. (optionally preceded by the word {\tt ALGEBRAIC}), followed by the name of
  39. the procedure to be defined, and followed by its formal parameters -- the
  40. symbols that will be used in the body of the definition to illustrate
  41. what is to be done. There are three cases:
  42. \begin{enumerate}
  43. \item No parameters. Simply follow the procedure name with a terminator
  44. (semicolon or dollar sign).
  45. \begin{verbatim}
  46. procedure abc;
  47. \end{verbatim}
  48. When such a procedure is used in an expression or command, {\tt abc()}, with
  49. empty parentheses, must be written.
  50. \item One parameter. Enclose it in parentheses {\em or\/} just leave at
  51. least one space, then follow with a terminator.
  52. \begin{verbatim}
  53. procedure abc(x);
  54. \end{verbatim}
  55. or
  56. \begin{verbatim}
  57. procedure abc x;
  58. \end{verbatim}
  59. \item More than one parameter. Enclose them in parentheses, separated by
  60. commas, then follow with a terminator.
  61. \begin{verbatim}
  62. procedure abc(x,y,z);
  63. \end{verbatim}
  64. \end{enumerate}
  65. Referring to the last example, if later in some expression being evaluated
  66. the symbols {\tt abc(u,p*q,123)} appear, the operations of the procedure
  67. body will be carried out as if {\tt X} had the same value as {\tt U} does,
  68. {\tt Y} the same value as {\tt p*q} does, and {\tt Z} the value 123. The
  69. values of {\tt X}, {\tt Y}, {\tt Z}, after the procedure body operations
  70. are completed are unchanged. So, normally, are the values of {\tt U},
  71. {\tt P}, {\tt Q}, and (of course) 123. (This is technically referred to as
  72. call by value.)\index{Call by value}
  73. The reader will have noted the word {\em normally\/} a few lines earlier. The
  74. call by value protections can be bypassed if necessary, as described
  75. elsewhere.
  76. \section{Procedure Body}\index{Procedure body}
  77. Following the delimiter that ends the procedure heading must be a {\em
  78. single} statement defining the action to be performed or the value to be
  79. delivered. A terminator must follow the statement. If it is a semicolon,
  80. the name of the procedure just defined is printed. It is not printed if a
  81. dollar sign is used.
  82. If the result wanted is given by a formula of some kind, the body is just
  83. that formula, using the variables in the procedure heading.
  84. {\it Simple Example:}
  85. If {\tt f(x)} is to mean {\tt (x+5)*(x+6)/(x+7)}, the entire procedure
  86. definition could read
  87. \begin{verbatim}
  88. procedure f x; (x+5)*(x+6)/(x+7);
  89. \end{verbatim}
  90. Then {\tt f(10)} would evaluate to 240/17, {\tt f(a-6)} to
  91. {\tt A*(A-1)/(A+1)}, and so on.
  92. {\it More Complicated Example:}
  93. Suppose we need a function {\tt p(n,x)} that, for any positive integer
  94. {\tt N}, is the Legendre polynomial\index{Legendre polynomials} of order
  95. {\em n}. We can define this operator using the
  96. textbook formula defining these functions:
  97. \begin{displaymath}
  98. p_n(x) = \displaystyle{1\over{n!}}\
  99. \displaystyle{d^n\over dy^n}\ \displaystyle{{1\over{(y^2 - 2xy + 1)
  100. ^{{1\over2}}}}}\Bigg\vert_{y=0}
  101. \end{displaymath}
  102. Put into words, the Legendre polynomial $p_n(x)$ is the result of
  103. substituting $y=0$ in the $n^{th}$ partial derivative with respect to $y$
  104. of a certain fraction involving $x$ and $y$, then dividing that by $n!$.
  105. This verbal formula can easily be written in {\REDUCE}:
  106. \begin{verbatim}
  107. procedure p(n,x);
  108. sub(y=0,df(1/(y^2-2*x*y+1)^(1/2),y,n))
  109. /(for i:=1:n product i);
  110. \end{verbatim}
  111. Having input this definition, the expression evaluation
  112. \begin{verbatim}
  113. 2p(2,w);
  114. \end{verbatim}
  115. would result in the output
  116. \begin{verbatim}
  117. 2
  118. 3*W - 1 .
  119. \end{verbatim}
  120. If the desired process is best described as a series of steps, then a group
  121. or compound statement can be used.
  122. \extendedmanual{\newpage}
  123. {\it Example:}
  124. The above Legendre polynomial example can be rewritten as a series of steps
  125. instead of a single formula as follows:
  126. \begin{verbatim}
  127. procedure p(n,x);
  128. begin scalar seed,deriv,top,fact;
  129. seed:=1/(y^2 - 2*x*y +1)^(1/2);
  130. deriv:=df(seed,y,n);
  131. top:=sub(y=0,deriv);
  132. fact:=for i:=1:n product i;
  133. return top/fact
  134. end;
  135. \end{verbatim}
  136. Procedures may also be defined recursively. In other words, the procedure
  137. body\index{Procedure body} can include references to the procedure name
  138. itself, or to other procedures that themselves reference the given
  139. procedure. As an example, we can define the Legendre polynomial through
  140. its standard recurrence relation:
  141. \begin{verbatim}
  142. procedure p(n,x);
  143. if n<0 then rederr "Invalid argument to P(N,X)"
  144. else if n=0 then 1
  145. else if n=1 then x
  146. else ((2*n-1)*x*p(n-1,x)-(n-1)*p(n-2,x))/n;
  147. \end{verbatim}
  148. The operator {\tt REDERR}\ttindex{REDERR} in the above example provides
  149. for a simple error exit from an algebraic procedure (and also a block).
  150. It can take a string as argument.
  151. It should be noted however that all the above definitions of {\tt p(n,x)} are
  152. quite inefficient if extensive use is to be made of such polynomials, since
  153. each call effectively recomputes all lower order polynomials. It would be
  154. better to store these expressions in an array, and then use say the
  155. recurrence relation to compute only those polynomials that have not already
  156. been derived. We leave it as an exercise for the reader to write such a
  157. definition.
  158. \section{Using LET Inside Procedures}
  159. By using {\tt LET}\ttindex{LET} instead of an assignment in the procedure
  160. body\index{Procedure body} it is possible to bypass the call-by-value
  161. \index{Call by value} protection. If {\tt X} is a formal parameter or local
  162. variable of the procedure (i.e. is in the heading or in a local
  163. declaration), and {\tt LET} is used instead of {\tt :=} to make an
  164. assignment to {\tt X}, e.g.
  165. \begin{verbatim}
  166. let x = 123;
  167. \end{verbatim}
  168. then it is the variable that is the value of {\tt X} that is changed.
  169. This effect also occurs with local variables defined in a block. If the
  170. value of {\tt X} is not a variable, but a more general expression, then it
  171. is that expression that is used on the left-hand side of the {\tt LET}
  172. statement. For example, if {\tt X} had the value {\tt p*q}, it is as if
  173. {\tt let p*q = 123} had been executed.
  174. \section{LET Rules as Procedures}
  175. The {\tt LET}\ttindex{LET} statement offers an alternative syntax and
  176. semantics for procedure definition.
  177. In place of
  178. \begin{verbatim}
  179. procedure abc(x,y,z); <procedure body>;
  180. \end{verbatim}
  181. one can write
  182. \begin{verbatim}
  183. for all x,y,z let abc(x,y,z) = <procedure body>;
  184. \end{verbatim}
  185. There are several differences to note.
  186. If the procedure body contains an assignment to one of the formal
  187. parameters, e.g.
  188. \begin{verbatim}
  189. x := 123;
  190. \end{verbatim}
  191. in the {\tt PROCEDURE} case it is a variable holding a copy of the first
  192. actual argument that is changed. The actual argument is not changed.
  193. In the {\tt LET} case, the actual argument is changed. Thus, if {\tt ABC}
  194. is defined using {\tt LET}, and {\tt abc(u,v,w)} is evaluated, the value
  195. of {\tt U} changes to 123. That is, the {\tt LET} form of definition
  196. allows the user to bypass the protections that are enforced by the call
  197. by value conventions of standard {\tt PROCEDURE} definitions.
  198. {\it Example:} We take our earlier {\tt FACTORIAL}\ttindex{FACTORIAL}
  199. procedure and write it as a {\tt LET} statement.
  200. \begin{verbatim}
  201. for all n let factorial n =
  202. begin scalar m,s;
  203. m:=1; s:=n;
  204. l1: if s=0 then return m;
  205. m:=m*s;
  206. s:=s-1;
  207. go to l1
  208. end;
  209. \end{verbatim}
  210. The reader will notice that we introduced a new local variable, {\tt S},
  211. and set it equal to {\tt N}. The original form of the procedure contained
  212. the statement {\tt n:=n-1;}. If the user asked for the value of {\tt
  213. factorial(5)} then {\tt N} would correspond to, not just have the value
  214. of, 5, and {\REDUCE} would object to trying to execute the statement
  215. 5 := $5-1$.
  216. If {\tt PQR} is a procedure with no parameters,
  217. \begin{verbatim}
  218. procedure pqr;
  219. <procedure body>;
  220. \end{verbatim}
  221. it can be written as a {\tt LET} statement quite simply:
  222. \begin{verbatim}
  223. let pqr = <procedure body>;
  224. \end{verbatim}
  225. To call {\em procedure\/} {\tt PQR}, if defined in the latter form, the empty
  226. parentheses would not be used: use {\tt PQR} not {\tt PQR()} where a call
  227. on the procedure is needed.
  228. The two notations for a procedure with no arguments can be combined. {\tt PQR}
  229. can be defined in the standard {\tt PROCEDURE} form. Then a {\tt LET}
  230. statement
  231. \begin{verbatim}
  232. let pqr = pqr();
  233. \end{verbatim}
  234. would allow a user to use {\tt PQR} instead of {\tt PQR()} in calling the
  235. procedure.
  236. A feature available with {\tt LET}-defined procedures and not with procedures
  237. defined in the standard way is the possibility of defining partial
  238. functions.\index{Function}
  239. \begin{verbatim}
  240. for all x such that numberp x let uvw(x)=<procedure body>;
  241. \end{verbatim}
  242. Now {\tt UVW} of an integer would be calculated as prescribed by the procedure
  243. body, while {\tt UVW} of a general argument, such as {\tt Z} or {\tt p+q}
  244. (assuming these evaluate to themselves) would simply stay {\tt uvw(z)}
  245. or {\tt uvw(p+q)} as the case may be.