[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

*To*: cl-iteration@SU-AI.ARPA*Subject*: PSL's FOR Macro*From*: Stan Shebs <SHEBS@UTAH-20.ARPA>*Date*: Mon 10 Dec 84 17:44:55-MST

The PSL FOR macro description is not very long, so here it is: (FOR . S:forms): any Macro The arguments to FOR are clauses; each clause is itself a list of a keyword and one or more arguments. The clauses may introduce local variables, specify return values and when the iteration should cease, have side-effects, and so on. Before going further, it is probably best to give some examples. (FOR (FROM I 1 10 2) (DO (PRINT I))) Prints the numbers 1 3 5 7 9 (FOR (IN U '(A B C)) (DO (PRINT U))) Prints the letters A B C (FOR (ON U '(A B C)) (DO (PRINT U))) Prints the lists (A B C) (B C) and (C) Finally, the function (DE ZIP (X Y) (FOR (IN U X) (IN V Y) (COLLECT (LIST U V)))) produces a list of 2 element lists, each consisting of the the corresponding elements of the three lists X, Y and Z. For example, (ZIP '(1 2 3 4) '(A B C) ) produces ((1 a)(2 b)(3 c)) The iteration terminates as soon as one of the (IN ..) clauses is exhausted. Note that the (IN ... ), (ON ...) and (FROM ...) clauses introduce local variables U, V or I, that are referred to in the action clause. All the possible clauses are described below. The first few introduce iteration variables. Most of these also give some means of indicating when iteration should cease. For example, if a list being mapped over by an IN clause is exhausted, iteration must cease. If several such clauses are given in a FOR expression, iteration ceases when one of the clauses indicates it should, whether or not the other clauses indicate that it should cease. (IN V1 V2) assigns the variable V1 successive elements of the list V2. This may take an additional, optional argument: a function to be applied to the extracted element or sublist before it is assigned to the variable. The following returns the sum of the lengths of all the elements of L. [Rather a kludge -- not sure why this is here. Perhaps it should come out again.] (DE LENGTHS (L) (FOR (IN N L LENGTH) (COLLECT (LIST N N))) is the same as (DE LENGTHS (L) (FOR (IN N L) (COLLECT (LIST (LENGTH N) (LENGTH N)))) ) but only calls LENGTH once. Using the (WITH ..) form to introduce a local LN may be clearer. For example, (SUMLENGTHS '((1 2 3 4 5)(a b c)(x y))) is ((5 5) (3 3) (2 2)) (ON V1 V2) assigns the variable V1 successive CDRs of the list V2. (FROM VAR INIT FINAL STEP) is a numeric iteration clause. The variable is first assigned INIT, and then incremented by step until it is larger than FINAL. INIT, FINAL, and STEP are optional. INIT and STEP both default to 1, and if FINAL is omitted the iteration continues until stopped by some other means. To specify a STEP with INIT or FINAL omitted, or a FINAL with INIT omitted, place NIL (the constant -- it cannot be an expression) in the appropriate slot to be omitted. FINAL and STEP are only evaluated once. (FOR VAR INIT NEXT) assigns the variable INIT first, and subsequently the value of the expression NEXT. INIT and NEXT may be omitted. Note that this is identical to the behavior of iterators in a DO. (WITH V1 V2 ... Vn) introduces N locals, initialized to NIL. In addition, each Vi may also be of the form (VAR INIT), in which case it is initialized to INIT. (DO S1 S2 ... Sn) causes the Si's to be evaluated at each iteration. There are two clauses which allow arbitrary code to be executed before the first iteration, and after the last. (INITIALLY S1 S2 ... Sn) causes the Si's to be evaluated in the new environment (i.e. with the iteration variables bound to their initial values) before the first iteration. (FINALLY S1 S2 ... Sn) causes the Si's to be evaluated just before the function returns. The next few clauses build up return types. Except for the RETURNS/RETURNING clause, they may each take an additional argument which specifies that instead of returning the appropriate value, it is accumulated in the specified variable. For example, an unzipper might be defined as (DE UNZIP (L) (FOR (IN U L) (WITH X Y) (COLLECT (FIRST U) X) (COLLECT (SECOND U) Y) (RETURNS (LIST X Y)))) This is essentially the opposite of ZIP. Given a list of 2 element lists, it unzips them into 2 lists, and returns a list of those 2 lists. For example, (unzip '((1 a)(2 b)(3 c))) returns is ((1 2 3)(a b c)). (RETURNS EXP) causes the given expression to be the value of the FOR. Returning is synonymous with returns. It may be given additional arguments, in which case they are evaluated in order and the value of the last is returned (implicit PROGN). (COLLECT EXP) causes the successive values of the expression to be collected into a list. Each value is APPENDed to the end of the list. (ADJOIN EXP), (ADJOINQ EXP) are similar to COLLECT, but a value is added to the result only if it is not already in the list. ADJOIN tests with EQUAL, ADJOINQ tests with EQ. (CONC EXP) causes the successive values to be NCONC'd together. (JOIN EXP) causes them to be appended. (UNION EXP), (UNIONQ EXP) are similar to JOIN, but only add an element to the list if it is not already there. UNION tests with EQUAL, UNIONQ tests with EQ. (INTERSECTION EXP), (INTERSECTIONQ EXP) compute the set of elements that are in all the sets iterated over. With INTERSECTION, elements are the same if EQUAL, with INTERSECTIONQ they are the same if EQ. (COUNT EXP) returns the number of times EXP was non-NIL. (SUM EXP), (PRODUCT EXP), (MAXIMIZE EXP), and (MINIMIZE EXP) do the obvious. Synonyms are summing, maximizing, and minimizing. (MAXIMAL EXP1 EXP2), (MINIMAL EXP1 EXP2) are more general than maximize and minimize. MAXIMAL determines the greatest value for EXP2 over the iteration, returning the value of EXP1 rather than the value of EXP2. As a particular case it is possible to return the value of an iteration variable for which some function attains a maximum (or minimum) value, e.g. (MAXIMAL x (f x)). As with other kinds of clauses, the user may "accumulate" the value of EXP1 into a variable by supplying a third expression which is the name of a variable. (ALWAYS EXP) returns T if EXP is non-NIL on each iteration. If EXP is ever NIL, the loop terminates immediately, no epilogue code, such as that introduced by finally is run, and NIL is returned. (NEVER EXP) is equivalent to (ALWAYS (NOT EXP)). (WHILE EXP) and (UNTIL EXP) Explicit tests for the end of the loop may be given using (WHILE EXP). The loop terminates if EXP becomes NIL at the beginning of an iteration. (UNTIL EXP) is equivalent to (WHILE (NOT EXP)). Both WHILE and UNTIL may be given additional arguments; (WHILE E1 E2 ... En) is equivalent to (WHILE (AND E1 E2 ... En)) and (UNTIL E1 E2 ... En) is equivalent to (UNTIL (OR E1 E2 ... En)). (WHEN EXP) causes a jump to the next iteration if EXP is NIL. (UNLESS EXP) is equivalent to (WHEN (NOT EXP)). FOR is a general iteration construct similar in many ways to the Lisp Machine and MACLISP LOOP construct, and the earlier Interlisp CLISP iteration construct. FOR, however, is considerably simpler, far more "lispy", and somewhat less powerful. All variable binding/updating still precedes any tests or other code. Also note that all WHEN or UNLESS clauses apply to all action clauses, not just subsequent ones. This fixed order of evaluation makes FOR less powerful than LOOP, but also keeps it considerably simpler. The basic order of evaluation is 1. bind variables to initial values (computed in the outer environment) 2. execute prologue (i.e., INITIALLY clauses) 3. while none of the termination conditions are satisfied: a. check conditionalization clauses (WHEN and UNLESS), and start next iteration if all are not satisfied. b. perform body, collecting into variables as necessary c. next iteration 4. (after a termination condition is satisfied) execute the epilogue (i.e., FINALLY clauses) FOR does all variable binding/updating in parallel. There is a similar macro, FOR*, which does it sequentially. (FOR* . S:forms): any Macro -------

- Prev by Date:
**Misc** - Next by Date:
**Re: LOOP and Reply to Boyer** - Previous by thread:
**Misc** - Next by thread:
**PSL's FOR Macro** - Index(es):