REDUCE

15.2 Procedure Body

Following the delimiter that ends the procedure heading must be a single statement defining the action to be performed or the value to be delivered. A terminator must follow the statement. If it is a semicolon, the name of the procedure just defined is printed. It is not printed if a dollar sign is used.

If the result wanted is given by a formula of some kind, the body is just that formula, using the variables in the procedure heading.

Simple Example:

If f(x) is to mean (x+5)*(x+6)/(x+7), the entire procedure definition could read

        procedure f x; (x+5)*(x+6)/(x+7);

Then f(10) would evaluate to 240/17, f(a-6) to A*(A-1)/(A+1), and so on.

More Complicated Example:

Suppose we need a function p(n,x) that, for any positive integer N, is the Legendre polynomial of order n. We can define this operator using the textbook formula defining these functions:

                              |
         1  dn        1       ||
pn(x) = n! dyn---2-----------1||
               (y  - 2xy + 1)2 y=0

Put into words, the Legendre polynomial pn(x) is the result of substituting y = 0 in the nth partial derivative with respect to y of a certain fraction involving x and y, then dividing that by n!.

This verbal formula can easily be written in REDUCE:

        procedure p(n,x);  
           sub(y=0,df(1/(y^2-2*x*y+1)^(1/2),y,n))  
               /(for i:=1:n product i);

Having input this definition, the expression evaluation

        2p(2,w);

would result in the output

           2  
        3*W  - 1 .

If the desired process is best described as a series of steps, then a group or compound statement can be used.

Example:

The above Legendre polynomial example can be rewritten as a series of steps instead of a single formula as follows:

        procedure p(n,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;

Procedures may also be defined recursively. In other words, the procedure body can include references to the procedure name itself, or to other procedures that themselves reference the given procedure. As an example, we can define the Legendre polynomial through its standard recurrence relation:

        procedure p(n,x);  
           if n<0 then rederr ~Invalid argument to P(N,X)~  
            else if n=0 then 1  
            else if n=1 then x  
            else ((2*n-1)*x*p(n-1,x)-(n-1)*p(n-2,x))/n;

The operator REDERR in the above example provides for a simple error exit from an algebraic procedure (and also a block). It can take a string as argument.

It should be noted however that all the above definitions of p(n,x) are quite inefficient if extensive use is to be made of such polynomials, since each call effectively recomputes all lower order polynomials. It would be better to store these expressions in an array, and then use say the recurrence relation to compute only those polynomials that have not already been derived. We leave it as an exercise for the reader to write such a definition.