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

Re: Case study: Macro forms as operators in Maclisp

For better or worse, let me describe what it is that Maclisp currently does
with the things in the car of a form, because it may bring to light some
potential problems in the ideas being discussed:

  If the object is a symbol, a functional property is looked for.
  If the object is some other kind of atom, I think an error is generated.
  Else if non-atomic, it is checked for one of a few special forms (LAMBDA
   forms, FUNARGs, and such) ...
   and finally if it's not one of those, it is normal Lisp EVAL'd to get 
   something that can be re-run through this procedure.
  After about 2 or 3 iterations it punts if it hasn't gotten something it
  can use.

The interesting thing is the case where the normal Lisp EVAL happens.
So if you take the following two definitions:
	(DEFUN DEMO () ((FIRST) '(A B)))
and you run them in the interpreter and compiler you get two different
effects. In the interpreter, Lisp EVAL means if it's a macro you get the
double-evaluation syndrome. So 
	((FIRST) '(A B))
will err out in the interpreter because the interpreter Lisp EVAL's the car
getting back CAR for the macro expansion and then re-eval'ing that to NIL and
then trying to funcall the NIL on '(A B) and losing. Interestingly, there is
a misfeature of MACROEXPAND in Maclisp such that
	(EVAL '((FIRST) '(A B))) loses
but	(EVAL (MACROEXPAND '((FIRST) '(A B)))) `wins' returning A.
(What the right thing to do here is very subjective, so I use the term
wins and loses *very* loosely.) Anyway, in the compiler, no EVALs are being
done, so
	((FIRST) '(A B))
is only macroexpanded in one pass and you end up with (CAR '(A B)) which 
it forgets needed the extra eval on the car of the form, resulting in an
accidental `correct' compilation of DEMO so that it will return A instead of
getting the NIL UNDEFINED FUNCTION OBJECT type error.

I sincerely hope that a whole pile of code relying on these oddities will not
be written as a result of this message, but I do hope it will point up that 
in different contexts, it may be very complicated to keep track of the number
of evaluations needed. 

I suspect what this says is that Maclisp should not allow random forms in the
car of an s-expression (requiring funcall if that's what the guy wants) and
if it sees random forms, it should assume they are macro forms, macroexpand
them WITHOUT evaluating the result, and then try to apply the expansion.
This would probably be the easiest scheme to retain consistency.