REDUCE

7.1 Introduction

In a PSL program the flow of control is described primarily by function application. A function may call any number of other functions, including itself. This allows complex operations to be described by a number of small functions, each of which implements a simple operation. In addition, PSL provides a number of other control constructs.

7.1.1 Conditionals

Conds and Ifs

(cond [U:form-list]): any open-compiled fexpr

A typical application of cond is shown below, the square brackets are used to indicate zero of more occurances of an expression.

    (COND ([(<predicate> [<action>])]))

The first form in each clause is treated as a predicate; the remaining (zero or more) forms are treated as if they were enclosed within a progn. The evaluation proceeds by sequentially evaluating the predicates in the order of their appearance until one evaluates to a non-nil value. Then the remaining forms in this clause are evaluated and the value of the last form is returned as the result. If only the predicate appears, then its value (if non-nil) becomes the value returned. If no predicate is non-nil then the result is nil. The following definition demonstrates the use of cond.

    (de size (data)  
      (cond ((pairp data) (length data))  
            ((stringp data) (string-length data))  
            ((vectorp data) (vector-size data))  
            (t 'unknown)))

This function will compute the length of lists strings and vectors.

The following macros are defined in the USEFUL module.

(if E:form S0:form [S:form]): any macro
The form S0 is evaluated if the test E is non-nil, otherwise the remaining forms S are evaluated, the value of the last is returned. If is a macro to simplify the writing of a common form of cond in which there are only two clauses and the antecedent of the second is t.

The expression

    (if (minusp number) 'negative 'positive)

is preferred over

    (cond ((minusp number) 'negative)  
            (t 'positive))

Notice that a single form is evaluated when the test expression E is non-nil but there may be any number of expressions evaluated when the value of E is nil.

Related macros for common cond forms are when and unless.

(when E:form [S:form]): any macro
When the value of the test expression E is non-nil the forms S are evaluated. The value of the last form is returned as the result. The result is nil if the test expresson E is nil.

(unless E:form [U:form]): any macro
If the value of E is nil then the forms S are evaluated. The result is nil if the test expression E is non-nil.
The boolean functions and and or (see Chapter 2), may be used as conditional forms. For example an expression like
 
(and (pairp x) (eq (car x) 'a))  

which relies upon the order of the evaluation of the arguments is often used. If and had evaluated the second argument first an error may have been generated. However, the arguments are always evaluated from left to right. Or may be used to retrieve a value as in the function definition below.

(de dispatch (data arguments)  
(apply (or (get data 'function) default-function)  
arguments))

In this example the function which is applied is either found on the property list of the data or it is a default. In reading such an expression one considers an argument to be preferred over anything which follows it. Note that the use of these functions as conditionals may yield code which is confusing. For example the code

 
(setq x (and y 3))  

will set x to 3 if y is bound to a value other than nil, otherwise x will be set to nil. It is recommended that the following be used instead.

(setq x (if y 3 nil))

The following version of if is defined in the module if. It is upward compatible with the if macro defined above. This version will accept the keywords then, else, and elseif. If a keyword appears immediately after the conditional expression of the if then the expression is taken to be in keyword form.

(if <expr> [then <expr> ... ][<elseif-part> ... ][else <expr> ... ]):
any expr
This is not the same notation used generally in the PSL manual. Square brackets enclose parts optionally present. The ellipses indicate arbitrary additional repetitions of the thing appearing just before them. The elseif-part may be one of two forms.
<elseif-part> = else if <expr> [then <expr> ... ]
<elseif-part> = else if <expr> [then <expr> ... ]