* New version of IRM New version of the IRM, updated to Medley. * moved to docs/medley-irm as discussed
105 lines
73 KiB
Plaintext
105 lines
73 KiB
Plaintext
INTERLISP-D REFERENCE MANUAL
|
||
CONDITIONALS AND ITERATIVE STATEMENTS
|
||
"9"9. LISTS AND ITERATIVE STATEMENTS
|
||
3
|
||
|
||
|
||
Medley gives you a large number of predicates, conditional functions, and control functions. Also, there is a complex ªiterative statementº facility which allows you to easily create complex loops and iterative constructs.
|
||
Data Type Predicates
|
||
1
|
||
|
||
Medley provides separate functions for testing whether objects are of certain commonly-used types:
|
||
(LITATOM(LITATOM (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns T if X is a symbol; NIL otherwise. Note that a number is not a symbol.
|
||
(SMALLP(SMALLP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a small integer; NIL otherwise. (The range of small integers is -65536 to +65535.
|
||
(FIXP(FIXP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a small or large integer; NIL otherwise.
|
||
(FLOATP(FLOATP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a floating point number; NIL otherwise.
|
||
(NUMBERP(NUMBERP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a number of any type, NIL otherwise.
|
||
(ATOM(ATOM (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns T if X is an atom (i.e. a symbol or a number); NIL otherwise.
|
||
(ATOM X) is NIL if X is an array, string, etc. In Common Lisp, CL:ATOM is defined equivalent to the Interlisp function NLISTP.
|
||
(LISTP(LISTP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a list cell (something created by CONS); NIL otherwise.
|
||
(NLISTP(NLISTP (Function) NIL NIL ("9") 1) X) [Function]
|
||
(NOT (LISTP X)). Returns T if X is not a list cell, NIL otherwise.
|
||
(STRINGP(STRINGP (Function) NIL NIL ("9") 1) X) [Function]
|
||
Returns X if X is a string, NIL otherwise.
|
||
(ARRAYP X) [Function]
|
||
Returns X if X is an array, NIL otherwise.
|
||
(HARRAYP X) [Function]
|
||
Returns X if it is a hash array object; otherwise NIL.
|
||
HARRAYP(HARRAYP (Function) NIL NIL ("9") 2) returns NIL if X is a list whose CAR is an HARRAYP, even though this is accepted by the hash array functions.
|
||
Note: The empty list, () or NIL, is considered to be a symbol, rather than a list. Therefore, (LITATOM NIL) = (ATOM NIL) = T and (LISTP NIL) = NIL. Take care when using these functions if the object may be the empty list NIL.
|
||
Equality Predicates
|
||
1
|
||
|
||
Sometimes, there is more than one type of equality. For instance, given two lists, you can ask whether they are exactly the same object, or whether they are two distinct lists that contain the same elements. Confusion between these two types of equality is often the source of program errors.
|
||
(EQ(EQ (Function) NIL NIL ("9") 2) X Y) [Function]
|
||
Returns T if X and Y are identical pointers; NIL otherwise. EQ should not be used to compare two numbers, unless they are small integers; use EQP instead.
|
||
(NEQ(NEQ (Function) NIL NIL ("9") 2) X Y) [Function]
|
||
The same as (NOT (EQ X Y))
|
||
(NULL(NULL (Function) NIL NIL ("9") 2) X) [Function]
|
||
(NOT(NOT (Function) NIL NIL ("9") 2) X) [Function]
|
||
The same as (EQ X NIL)
|
||
(EQP(EQP (Function) NIL NIL ("9") 2) X Y) [Function]
|
||
Returns T if X and Y are EQ, or if X and Y are numbers and are equal in value; NIL otherwise. For more discussion of EQP and other number functions, see Chapter 7.
|
||
EQP also can be used to compare stack pointers (Section 11) and compiled code (Chapter 10).
|
||
(EQUAL(EQUAL (Function) NIL NIL ("9") 2) X Y) [Function]
|
||
EQUAL returns T if X and Y are one of the following:
|
||
1. EQ
|
||
2. EQP, i.e., numbers with equal value
|
||
3. STREQUAL, i.e., strings containing the same sequence of characters
|
||
4. Lists and CAR of X is EQUAL to CAR of Y, and CDR of X is EQUAL to CDR of Y
|
||
EQUAL returns NIL otherwise. Note that EQUAL can be significantly slower than EQ.
|
||
A loose description of EQUAL might be to say that X and Y are EQUAL if they print out the same way.
|
||
(EQUALALL(EQUALALL (Function) NIL NIL ("9") 2) X Y) [Function]
|
||
Like EQUAL, except it descends into the contents of arrays, hash arrays, user data types, etc. Two non-EQ arrays may be EQUALALL if their respective componants are EQUALALL.
|
||
Note: In general, EQUALALL descends all the way into all datatypes, both those you've defined and those built into the system. If you have a data structure with fonts and pointers to windows, EQUALALL will descend those also. If the data structures are circular, as windows are, EQUALALL can cause stack overflow.
|
||
Logical Predicates
|
||
1
|
||
|
||
(AND X1 X2 ... XN)(AND% X1% X2% ...% XN%) (Function) %(AND% X1% X2% ...% XN%) NIL ("9") 3) [NLambda NoSpread Function]
|
||
Takes an indefinite number of arguments (including zero), that are evaluated in order. If any argument evaluates to NIL, AND immediately returns NIL, without evaluating the remaining arguments. If all of the arguments evaluate to non-NIL, the value of the last argument is returned. (AND) => T.
|
||
(OR X1 X2 ... XN)(OR% X1% X2% ...% XN%) (Function) %(OR% X1% X2% ...% XN%) NIL ("9") 3) [NLambda NoSpread Function]
|
||
Takes an indefinite number of arguments (including zero), that are evaluated in order. If any argument is non-NIL, the value of that argument is returned by OR (without evaluating the remaining arguments). If all of the arguments evaluate to NIL, NIL is returned. (OR) => NIL.
|
||
AND and OR can be used as simple logical connectives, but note that they may not evaluate all of their arguments. This makes a difference if some of the arguments cause side-effects. This also means you can use AND and OR as simple conditional statements. For example: (AND (LISTP X) (CDR X)) returns the value of (CDR X) if X is a list cell; otherwise it returns NIL without evaluating (CDR X). In general, you should avoid this use of AND and OR in favor of more explicit conditional statements in order to make programs more readable.
|
||
COND Conditional Function
|
||
1
|
||
|
||
(COND CLAUSE1 CLAUSE2 ... CLAUSEK)(COND% CLAUSE1% CLAUSE2% ...% CLAUSEK%) (Function) %(COND% CLAUSE1% CLAUSE2% ...% CLAUSEK%) NIL ("9") 3) [NLambda NoSpread Function]
|
||
COND takes an indefinite number of arguments, called clauses. Each CLAUSEi is a list of the form (Pi Ci1 ... CiN), where Pi is the predicate, and Ci1 ... CiN are the consequents. The operation of COND can be paraphrased as:
|
||
IF P1 THEN C11 ... C1N ELSEIF P2 THEN C21 ... C2N ELSEIF P3 ...
|
||
The clauses are considered in sequence as follows: The predicate P1 of the clause CLAUSEi is evaluated. If the value of P1 is ªtrueº (non-NIL), the consequents Ci1 ... CiN are evaluated in order, and the value of the COND is the value of the last expression in the clause. If P1 is ªfalseº (EQ to NIL), then the remainder of CLAUSEi is ignored, and the next clause, CLAUSEi+1, is considered. If no Pi is true for any clause, the value of the COND is NIL.
|
||
If a clause has no consequents, and has the form (Pi), then if Pi evaluates to non-NIL, it is returned as the value of the COND. It is only evaluated once.
|
||
Example:
|
||
¬(DEFINEQ (DOUBLE (X)
|
||
(COND ((NUMBERP X) (PLUS X X))
|
||
((STRINGP X) (CONCAT X X))
|
||
((ATOM X) (PACK* X X))
|
||
(T (PRINT "unknown") X)
|
||
((HORRIBLE-ERROR))]
|
||
(DOUBLE)
|
||
¬(DOUBLE 5)
|
||
10
|
||
¬(DOUBLE "FOO")
|
||
"FOOFOO"
|
||
¬(DOUBLE 'BAR)
|
||
BARBAR
|
||
¬(DOUBLE '(A B C))
|
||
"unknown"
|
||
(A B C)
|
||
A few points about this example: Notice that 5 is both a number and an atom, but it is ªcaughtº by the NUMBERP clause before the ATOM clause. Also notice the predicate T, which is always true. This is the normal way to indicate a COND clause which will always be executed (if none of the preceeding clauses are true). (HORRIBLE-ERROR) will never be executed.
|
||
The IF Statement
|
||
1
|
||
|
||
The IF statement(IF% STATEMENT NIL IF% statement NIL ("9") 4) lets you write conditional expressions that are easier to read than using COND directly. CLISP translates expressions using IF, THEN, ELSEIF, or ELSE (or their lowercase versions) into equivalent CONDs. In general, statements of the form:
|
||
(if AAA then BBB elseif CCC then DDD else EEE)
|
||
are translated to:
|
||
(COND (AAA BBB)
|
||
(CCC DDD)
|
||
(T EEE))
|
||
The segment between IF or ELSEIF and the next THEN corresponds to the predicate of a COND clause, and the segment between THEN and the next ELSE or ELSEIF as the consequent(s). ELSE is the same as ELSEIF T THEN. These words are spelling corrected using the spelling list CLISPIFWORDSPLST. You may also use lower-case versions (if, then, elseif, else).
|
||
If there is nothing following a THEN, or THEN is omitted entirely, the resulting COND clause has a predicate but no consequent. For example, (if X then elseif ...) and (if X elseif ...) both translate to (COND (X) ...)ÿÿ |