123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- A number of useful options can be defined by Loading Useful.
- Descriptions follow.
- BACKQUOTE and friends
- ------------------
- (Note that the special symbols decribed here will only work in LISP
- syntax, not RLISP. In RLISP you may simply use the functions
- BACKQUOTE, UNQUOTE, UNQUOTEL, and UNQUOTED)
- The backquote symbol "`" is a read macro which introduces a quoted
- expression which may contain the unquote symbols comma "," and
- comma-atsign ",@". Any appropriate form consisting of the unquoted
- expression, calls to the function cons, and quoted expressions are
- produced so that the resulting expression looks like the quoted one
- except that the values of the unquote expressions are substitued in the
- appropriate place. ",@" splices in the value of the subsequent
- expression (i.e. strips off the outer layer of parentheses). Thus
- `(a (b ,x) c d ,@x e f)
- is equivalent to
-
- (cons 'a (cons (list 'b x) (append '(c d) (append x '(e f)))))
- In particular, if x is bound to (1 2 3) this will evaluate to
- (a (b (1 2 3)) c d 1 2 3 e f)
- ",." is like ",@", except it may use destructive operations on its
- argument.
- DESETQ
- ------
- DESETQ is a destructuring setq. That is, the first argument is a piece
- of list structure whose atoms are all ids. Each is setq'd to the
- corresponding part of the second argument. For instance
- (desetq (a (b) . c) '((1) (2) (3) 4))
-
- setq's a to (1), b to 2, and c to ((3) 4).
- DEFMACRO
- --------
- DEFMACRO is a useful tool for defining macros. A DEFMACRO form looks
- like
- (defmacro <name> <pattern> <s1> <s2> ... <sN>)
- The <pattern> is an S-expression made of pairs and ids. It is matched
- against the arguments of the macro much like the first argument to
- desetq. All of the non-nil ids in <pattern> are local variables which
- may be used freely in the body (the <si>). When the macro is called
- the <si> are evaluated as in a progn with the local variables in
- <pattern> appropriately bound, and the value of <sN> is returned.
- DEFMACRO is often used with backquote.
- DEFLAMBDA
- ---------
- Another macro defining macro similar to DEFMACRO is DEFLAMBDA. The
- arguments to DEFLAMBDA are identical to those for DE. The resulting
- macro is simply application of a lambda expression. Thus a function
- defined with DEFLAMBDA will have semantics identical to that of a
- function defined with DE, modulo the ability to dynamically redefine
- the function. This is a convenient way to cause functions to be open
- compiled.
- For example, if (NEW-FOO X Y) should return (LIST X Y (LIST X Y)) we do
- not want it to be a simple substitution style macro, in case one of the
- actual arguments has side effects, or is expensive to compute. If we
- define it by
- (DEFLAMBDA NEW-FOO (X Y) (LIST X Y (LIST X Y)))
- then we will have the desired behaviour. In particular,
- (NEW-FOO (BAR) (SETQ BAZ (BOOZE)))
- will expand to
- ((LAMBDA (X Y)
- (LIST X Y (LIST X Y)) )
- (BAR)
- (SETQ BAZ (BOOZE)) )
- PROG1
- -----
- PROG1 evaluates its arguments in order, like PROGN, but returns the
- value of the first.
- LET and LET*
- ------------
- LET is a macro giving a more perspicuous form for writing lambda
- expressions. The basic form is
- (let ((v1 i1) (v2 i2) ...(vN iN))
- s1
- s2
- ...
- sN)
- The i's are evaluated (in an unspecified order), and then the v's are
- bound to these values, the s's evaluated, and the value of the last
- is returned. Note that the i's are evaluated in the outer environment
- before the v's are bound.
- LET!* is just like LET, except that it makes the assignments
- sequentially. That is, the first binding is made before the value
- for the second one is computed.
- MACROEXPAND
- -----------
- MACROEXPAND is a useful tool for debugging macro definitions. If given
- one argument, MACROEXPAND will all expand all the macros in that form.
- Often we wish more control over this process. For example, if a macro
- expands into a let, we may not wish to see the LET itself expanded to a
- lambda expression. Therefor additional arguments may be given to
- MACROEXPAND. If these are supplied, only they should be macros, and
- only those specified will be expanded.
- PUSH and POP
- ------------
- These are convenient macros for adding and deleting things from the
- head of a list. (push item stack) is equivalent to (setq stack (cons
- item stack)), and (pop stack) does (setq stack (cdr stack)) and
- returns the item popped off stack. An additional argument may be
- supplied to pop, in which case it is a variable which is setq'd to the
- popped value.
- INCR and DECR
- -------------
- These are convenient macros for incrementing and decrementing numeric
- variables. (incr i) is equivalent to (setq i (add1 i)) and (decr i) to
- (setq i (sub1 i)). Additional arguments may be supplied, which are
- summed and used as the amounts by to increment or decrement.
- DO, DO*, DO-LOOP, and DO-LOOP*
- ------------------------------
- The DO macro is a general iteration construct similar to that of LISPM
- and friends. However, it does differ in some details; in particular it
- is not compatible with the "old style DO" of MACLISP (which is a crock
- anyway), nor does it support the "no end test means once only"
- convention (which was just an ugly kludge to get an initialized prog).
- DO has the form
- (do (i1 i2 ... iN)
- (test r1 r2 ... rK)
- s1
- s2
- ...
- sM)
- where there may be zero or more i's, r's, and s's. In general the
- i's will have the form
- (var init step)
- On entry to the DO form, all the inits are evaluated, then the
- variables are bound to their respective inits. The test is evaluated,
- and if non-nil the form evaluates the r's and returns the value of the
- last one. If none are supplied it returns nil. If the test evaluates
- to nil the s's are evaluated, the variables are assigned the values of
- their respective steps in parallel, and the test evaluated again. This
- iteration continues until test evaluates to a non-nil value. Note that
- the inits are evaluated in the surrounding environment, while the steps
- are evaluated in the new environment. The body of the DO (the s's) is
- a prog, and may contain labels and GO's, though use of this is
- discouraged. It may be changed at a later date. RETURN used within a
- DO will return immediately without evaluating the test or exit forms
- (r's).
- There are alternative forms for the i's: If the step is omitted, the
- variable's value is left unchanged. If both the init and step are
- omitted or if the i is an id it is initialized to nil, and left
- unchanged. This is particularly useful for introducing dummy variables
- which will be setq'd inside the body.
- DO* is like DO, expcept the variable bindings and updatings are done
- sequentially instead of in parallel.
- DO-LOOP is like Do, except that it takes an additional argument, a
- prologue. The general form is
- (do-loop (i1 i2 ... iN)
- (p1 p2 ... pJ)
- (test r1 r2 ... rK)
- s1
- s2
- ...
- sM)
- This is executed just like the corresponding DO, except that after the
- bindings are established and initial values assigned, but before the
- test is first executed the pi's are evaluated, in order. Note that the
- pi's are all evaluated exactly once (assuming that none of the pi's err
- out, or otherwise throw to a surrounding context). DO-LOOP* does the
- variable bindings and undates sequentially instead of in parallel.
- IF, WHEN, and UNLESS for If and Only If Statements
- --------------------------------------------------
- IF is a macro to simplify the writing of a common form of COND where
- there are only two clauses and the antecedent of the second is t.
- (if <test> <then-clause> <else1>...<elseN>)
- The <then-clause> is evaluated if and only if the test is non-nil,
- otherwise the elses are evaluated, and the last returned. There may be
- zero elses.
- Related macros for common COND forms are WHEN and UNLESS.
- (when <test> s1 s2 ... sN)
- evaluates the si and returns the value of sN if and only if <test> is
- non-nil. Otherwise WHEN returns nil.
- (unless <test> s1 s2 ... sN) <=> (when (not <test>) s1 s2 ... sN).
- PSETQ and PSETF
- ---------------
- (psetq var1 val1 var2 val2 ... varN valN) setq's the vars to the
- corresponding vals. The vals are all evaluated before any assignments
- are made. That is, this is a parallel setq.
- PSETF is to SETF as PSETQ is to SETQ.
- SETF
- ----
- USEFUL contains an expanded version of the standard SETF macro. The
- principal difference from the default is that it always returns the
- the thing assigned (i.e. the right hand side). For example,
- (setf (cdr foo) '(x y z))
- returns '(x y z). In the default SETF the return value is
- indeterminate.
- USEFUL also makes several more functions known to SETF. All the c...r
- functions are included. LIST and CONS are also include, and are
- similar to desetq. For example,
- (setf (list (cons a b) c (car d)) '((1 2) 3 4 5))
- sets a to 1, b to (2), c to 3, and rplaca's the car of d to 4. It
- returns ((1 2) 3 4 5).
- SHARP-SIGN MACROS
- ------------------
- USEFUL defines several MACLISP style sharp sign read macros. Note that
- these only work with the LISP reader, not RLISP. Those currently
- included are
- #' : this is like the quote mark ' but is for FUNCTION instead of
- QUOTE.
- #/ : this returns the numeric form of the following character
- read without raising it. For example #/a is 97 while
- #/A is 65.
- #\ : This is a read macro for the CHAR macro, described in the PSL
- manual. Not that the argument is raised, if *RAISE it non-nil.
- For example, #\a = #\A = 65, while #\!a = #\(lower a) = 97.
- Char has been redefined in USEFUL to be slightly
- more table driven -- users can now add new "prefixes" such as
- META or CONTROL: just hang the appropriate function (from integers
- to integers) off the char-prefix-function property of the "prefix".
- A LARGE number of additional alias for various characters have been
- added, including all the "standard" ASCII names like NAK and DC1.
- #. : this causes the following expression to be evaluated at read
- time. For example, `(1 2 #.(plus 1 2) 4) reads as (1 2 3 4)
-
- #+ : this reads two expressions, and passes them to the if_system
- macro. That is, the first should be a system name, and if
- that is the current system the second argument is returned by
- the reader. If not, nil is returned. #- is similar, but
- causes the second arg to be returned only if it is NOT the
- current system. Note that this does NOT use splice macros,
- since PSL doesn't have them (I don't really know why not -- at
- the very least there ought to be a way to tell the reader
- "ignore this", even if splice macros are thought to be a
- kludge).
- FOR
- ---
- FOR is a general iteration construct similar in many ways to the Lisp
- Machine LOOP construct, and the earlier InterLISP CLISP iteration
- construct. FOR, however, is considerably simpler, far more "lispy",
- and somewhat less powerful. FOR will only work in LISP syntax. In
- fact, loading FOR will, for the time being, "break" RLISP, as it
- redefines the FOR macro. It is hoped that eventually the RLISP parser
- will be modified to emit calls on this new FOR macro instead of the old
- one.
- 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, have side-effects, when the iteration
- should cease, and so on. Before going further, it is probably best to
- give an example. The following function will zip together three lists
- into a list of three element lists.
- (de zip3 (x y z) (for (in u x) (in v y) (in w z) (collect (list u v w))))
- The three IN clauses specify that their first argument should take
- successive elements of the respective lists, and the COLLECT clause specifies
- that the answer should be a list built out of its argument. For
- example, (zip3 '(1 2 3 4) '(a b c d) '(w x y z)) is
- ((1 a w)(2 b x)(3 c y)(4 d z)).
- Following are described all the possible clauses. The first few
- introduce iteration variables. Most of these also give some means of
- indicating when iteration should cease. For example, when a list being
- mapped over by an IN clause is exhausted, iteration must cease. If
- several such clauses are given in FOR expression, iteration will cease
- whenever on 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 SumLengths (L) (for (in N L length) (sum N)))
-
- For example, (SumLengths '((1 2 3 4 5)(a b c)(x y))) is 10.
- (on v1 v2) assigns the varaible v1 successive cdrs of the list v2.
- (from var init final step) is a numeric 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 will continue 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 behaviour 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
- will be initialized to init.
- There are two clauses which allow arbitrary code to be executed before
- the first iteration, and after the last. (initially s1 s2 ... sN) will
- cause 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.
- (do s1 s2 ... sN) causes the si's to be evaluated at each iteration.
- 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 unzip3 (L)
- (for (in u L) (with X Y Z)
- (collect (car U) X)
- (collect (cadr U) Y)
- (collect (caddr U) Z)
- (returns (list X Y Z))))
- This is essentially the opposite of zip3. Given a list of three element
- lists, it unzips them into three lists, and returns a list of those
- three lists. For example, (unzip '((1 a w)(2 b x)(3 c y)(4 d z)))
- is ((1 2 3 4)(a b c d)(w x y z)).
- (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 succesive values of the expression to be
- collected into a list.
- (adjoin exp) is similar, but only adds an element to the list if it is
- not equal to anything already there.
- (adjoinq exp) is like adjoin, but uses eq instead of equal.
- (conc exp) causes the succesive values to be nconc'd together.
- (join exp) causes them to be appended.
- (union exp) forms the union of all the exp
- (unionq exp), (intersection exp), (intersectionq exp) are similar, but
- use the specified function instead of union.
- (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.
- (always exp) will return t if exp is non-nil on each iteration. If exp
- is ever nil, the loop will terminate immediately, no epilogue code,
- such as that introduced by finally will be run, and nil will be
- returned. (never exp) is equivlent to (always (not exp)).
- Explicit tests for the end of the loop may be given using (while exp).
- The loop will terminate 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) will cause a jump to the next iteration if exp is nil.
- (unless exp) is equivalent to (when (not exp)).
- Unlike MACLISP and clones' LOOP, FOR does all variable binding/updating
- in parallel. There is a similar macro, FOR*, which does it
- sequentially. All variable binding/updating still preceeds 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:
- 4) check conditionalization clauses (WHEN and UNLESS), and start next
- iteration if all are not satisfied.
- 5) perform body, collecting into variables as necessary
- 6) next iteration
- 7) (after a termination condition is satisfied) execute the epilogue (i. e.
- FINALLY clauses)
- DEFSWITCH
- ---------
- Defswitch provides a convenient machanism for declaring variables whose
- values need to be set in a disciplined manner. It is quite similar to
- T's DEFINE-SWITCH. The form of a defswitch expression is
- (defswitch <name> <var> [<read-action> {<set-action>}])
- This declares <name> to be a function of no arguments for deterimining
- the value of the variable <var>. <var> is declared fluid. SETF
- will set the value of <var> when given a call on <name> as its first
- argument. When <name> is called <read-action> will be evaluated
- (after the value of the variable is looked up). When it is set the
- <set-action>s will be evaluated (before the value is set). <name> may
- be used as a "free" variable in the <read-action> and <set-action>s, in
- which case it will hold the current value and new value, respectively.
- If <var> is nil an uninterned id will be used for the variable.
- Suppose we wish to keep a list in a variable, FOO, but also want to
- always have it's length available in FOOLENGTH. We can do this by
- always accessing FOO by a function as follows:
- (defswitch FOO nil nil (setq FOOLENGTH (length FOO)))
|