Common Lisp 笔记

《On Lisp》

On Lisp, P31(3.1 Functional Design)

A destructive function is one that can alter the arguments passed to it. However, even destructive functions usually work by returning values: you have to assume that nreverse will recycle lists you give to it as arguments, but you still can't assume that ti will reverse them. As before, the reversed list has to be found in return value. You still can't write

in the middle of a function and assume that afterwards lst will be reversed. This is what happens in most implementations:

To reverse lst , you would have to set lst to the return value, as with plain reverse .

On Lisp, P36(3.4 Functional Interface)

A corollary of convention above is that functions shouldn't return anything that isn't safe to modify. Thus one should avoid writing functions whose return values incorporate quoted objects. If we define exclaim so that its return value incorporates a quoted list,

Then any later destructive modification of the return value

could alter the list within the function:

To make exclaim proof against such proglems, it should be written:

There is one major exception to the rule that functions shouldn't return quoted lists: the functions which generate macro expansions. Macro expanders can safely incorporate quoted lists in the expansions they generate, if the expansions are going straight to the compiler.

On Lisp, P87(7.2 Backquote)

The comma causes the list (1 2 3) to be inserted in place of b , while the comma-at causes the elements of the list to be inserted there. There are some additional restrictions on the use of comma-at:

  1. In order for its argument to be spliced, comma-at must occur within a sequence. It's an error to say something like `,@b because there is nowhere to splice the value of b.
  2. The object to be spliced must be a list, unless it occurs last. The expression `(a ,@1) will evaluate to (a . 1) , but attempting to splice an atom into the middle of a list, as in `(a ,@1 b) , will cause an error.

...The effect of comma-at can be achieved without using backquote. The expression `(a ,@b c) is equal to (cons 'a (append b (list 'c))) , for example. Comma-at exists only to make such expression-generating expressions more readable.

On Lisp, P102(7.9 Dependence On Macros)

CLTL2 Says that “a macro definition must be seen by the compiler before the first use of the macro.” Implementations vary in how they respond to violations of this rule. Fortunately it's easy to avoid both types of problem. If you adhere to the following two principles, you need never worry about state or nonexistent macro definitions:

  1. Define macros before functions (or macros) which call them.
  2. When a macro is redefined, also recompile all the functions (or macros) which call it — directly or via other macors.

It has been suggested that all the macros in a program be put in a separate file, to make it easier to ensure that macro definitions are compiled first. That's taking things too far. It would be resonable to put general-purpose macros like while into a separate file, but general-purpose utilities ought to be separated from the rest of a program anyway, whether they're functions or macros.

Some macros are written just for use in one specific part of a program, and these should be defined with the code which uses them. So long as the definition of each macro appears before any calls to it, your programs will compile fine. Collecting together all your macros, simply because they're macros, would do nothing but make your code harder to read.

On Lisp, P129(9.7 Avoiding Capture with Gensyms)

In CLTL2 Common Lisp, the number in a gensym's printed representation comes from *gensym-counter* , a global variable always bound to an integer. By resetting this counter we can cause two gensyms to print the same

but they won't be identical.