[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
> Date: Tue, 3 Nov 87 14:51:07 -0500 (EST)
> From: Ayami Ogura <firstname.lastname@example.org>
> Subject: FEXPRs
> Does anyone know of a kcl equivalent for FEXPR? I believe it is a MacLisp
> concept, referring to reserved word functions. A FEXPR takes only one
> formal local variable, and when it is called, its formal variable is bound
> to the list of arguments as they appeared, not to their values. [...]
The short answer is that there is no exact equivalent, but you can, if
you wish, get a reasonable approximation by defining both a macro (to put
a quote around the argument list) and a function (to actually process the
arguments). If you are writing the sort of FEXPR that involves calls to
EVAL, however, you would do better to abandon the FEXPR approach and write
a macro for the whole thing.
Here is one simple way to define a macro/function combination that
imitates a FEXPR:
(defmacro defun-fexpr (name (var) &body body)
`(defmacro ,name (&rest ,var)
`((lambda (,',var) . ,',body) ',,var)))
To explain why user-defined FEXPRs are not available in Common Lisp
requires a longer answer.
"FEXPR" can just be another term for "special form", but it is more
often used to refer to a particular means of implementing special forms.
It comes from Lisp 1.5, where it was the name of the property used to
store the functions that interpreted special forms. Compiled FEXPRs were
called FSUBRs. This mechanism was maintained in MacLisp, so there you
could define something like IF by:
(cond ((eval (car form)) (eval (cadr form)))
(t (eval (caddr form)))))
Common Lisp (and hence KCL) contains built-in special forms, but it was
decided to disallow user-defined special forms. The only way to define
operations that do not follow the normal evaluation rules in Common Lisp
is to define them as macros.
The reason for this decision is given on page 57 of Steele. A longer
discussion of such issues can be found in Kent Pitman's paper "Special
Forms in Lisp", on p. 179ff of the Conference Record of the 1980 Lisp
This is largely a reaction to the use of FEXPRs to define control
structures and the like. Such FEXPRs call EVAL. FEXPRs that are
just to avoid some explicit quoting (e.g., when defining things
like TRACE) aren't such a problem, but it is difficult to allow
one without also allowing the other.
The main problem is that compilers (and other programs that analyze
programs) can't properly understand expressions that involve special
forms. For example, suppose IF were defined as above and the compiler
wanted to compile
(if (> x 3) (- x 3) x)
The compiler can't tell that the arguments to IF are interpreted as
expressions (given to EVAL) without an analysis of IF's definition
that, while perhaps possible in such simple cases, is not possible
in general. And so, it can't compile these arguments; it just emits
code that passes them to IF as-is. In a sense this is what you want:
IF is supposed to receive them as-is. But this makes it a rather
poor definition of a conditional: all variables used in IF expressions
must be declared special, and IFs are always essentially interpreted.
Any program that preprocesses Lisp course code will have similar problems.
For example, some object systems want to replace occurrences of instance
variables with code that refers to the corresponding slot in the object.
To do this, the object system needs to be able to tell which symbols
are variables. In the expression above, it wouldn't know whether to
replace X or not.
Macros do not share this problem because expressions involving macro calls
can be expanded until no references to the macros remain. Programs don't
have to analyze the macro calls; they can analyze the expansions instead.
The expansions may still involve built-in special forms, but these are a
fixed set, and the analyzing programs can know what they all do.
Jeff Dalton, JANET: J.Dalton@uk.ac.ed
AI Applications Institute, ARPA: J.Daltonemail@example.com
Edinburgh University. UUCP: ...!ukc!ed.ac.uk!J.Dalton