[Apologies for double mailings -- could we agree on a name for a
mailing list to be kept at SU-AI which would just be those
individuals in COMMON-LISP@SU-AI which are not also on LISP-FORUM@MC]
There were two suggestions in my note, and lambda-macros relate
to only one of then, namely the first one
FIRST SUGGESTION:
In the context of ((<something> . . .) a1 a2), have EVAL macroexpand
the part (<something> . . .) and "try again" before recursively
evaluating it. This will have the incompatible effect that
(defmacro foo () 'LIST)
((foo) 1 2)
no longer causes an error (unbound variable for LIST), but will rather
first expand into (list 1 2), which then evaluates to (1 2).
Note that for clarity, I've added the phrase "try again", meaning to
look at the form as see if it is recognized explicitly as, say, some
special form, or some subr application.
The discussion from last year, which resulted in the name "lambda-macros"
centered around finding a separate (but equal?) mechanism for code-expansion
for non-atomic forms which appear in a function place; my first suggestion
is to change EVAL (and compiler if necessary) to call the regular macroexpander
on any form which looks like some kind of function composition, and thus
implement a notion of "Meta-Composition" which is context free. It would be
a logical consequence of this notion that eval'ing (FUNCTION (FROTZ 1)) must
first macroexpand (FROTZ 1), so that #'(FPOSITION ...) could work in the
contexts cited about MAP. However, it is my second suggestion that would
not work in the context of an APPLY -- it is intended only for the EVAL-
of-a-form context -- and I'm not sure if that has been fully appreciated
since only RMS appears to have alluded to it.
However, I'd like to offer some commentary on why context-free
"meta-composition" is good for eval, yet why context-free "evaluation"
is bad:
1) Context-free "evaluation" is SCHEME. SCHEME is not bad, but it is
not LISP either. For the present, I believe the LISP community wants
to be able to write functions like:
(DEFUN SEMI-SORT (LIST)
(IF (GREATERP (FIRST LIST) (SECOND LIST))
LIST
(LIST (SECOND LIST) (FIRST LIST))))
Correct interpretation of the last line means doing (FSYMEVAL 'LIST)
for the instance of LIST in the "function" position, but doing (more
or less) (SYMEVAL 'LIST) for the others -- i.e., EVAL acts differently
depending upon whether the context is "function" or "expression-value".
2) Context-free "Meta-composition" is just source-code re-writing, and
there is no ambiguity of reference such as occured with "LIST" in the
above example. Take this example:
(DEFMACRO GET-SI (STRING)
(SETQ STRING (TO-STRING STRING))
(INTERN STRING 'SI))
(DEFUN SEE-IF-NEW-ATOM-LIST (LIST)
((GET-SI "LIST") LIST (GET-SI "LIST")))
Note that the context for (GET-SI "LIST") doesn't matter (sure, there
are other ways to write equivalent code but . . .)
Even the following macro definition for GET-SI results in perfectly
good, unambiguous results:
(DEFMACRO GET-SI (STRING)
`(LAMBDA (X Y) (,(intern (to-string string) 'SI) X Y)))
For example, assuming that (LAMBDA ...) => #'(LAMBDA ...),
(SEE-IF-NEW-ATOM-LIST 35) => (35 #'(LAMBDA (X Y) (LIST X Y)))
The latter (bletcherous) example shows a case where a user ** perhaps **
did not intend to use (GET-SI...) anywhere but in function context --
he simply put in some buggy code. The lambda-macro mechanism would require
a user to state unequivocally that a macro-defintion in precisely one
context; I'd rather not be encumbered with separate-but-parallel machinery
and documentation -- why not have this sort of restriction on macro usage
contexts be some kind of optional declaration?
Yet my second suggestion involves a form which could not at all be interpreted
in "expression-value" context:
SECOND SUGGESTION
Let FMACRO have special significance for macroexpansion in the context
((FMACRO . <fun>) . . .), such that this form is a macro call which is
expanded by calling <fun> on the whole form.
Thus (LIST 3 (FMACRO . <fun>)) would cause an error. I believe this
restriction is more akin to that which prevents MACROs from working
with APPLY.