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

Re: question about Quasiquote

re: I've just searched through a pile of code I've written without finding
    a single example that uses QUASIQUOTE non-zero nesting level.  Non-zero
    nesting levels are used mainly for macro-defining macros like (beware
    incoming Common Lisp syntax)

    (defmacro deffrob (head tail)
      `(progn (defmacro behead (x)
		`(setf ,,head ,x))
	      (defmacro betail (y)
		`(setf ,,tail ,y))))

    but I don't seem to write code like this myself.

Evidently not.  I'll just bet that you thought your example had the
simple, obvious meaning of:

    Given a shorthand form like  (DEFFROB (CAR X) (CDR X)),  write me 
    a couple of macros that look like this:

        (defmacro behead (x) `(SETF (CAR X) ,x))
        (defmacro betail (y) `(SETF (CDR X) ,y))

    realizing that the X in the (CAR X) is not connected to the bound 
    argument variable of the defmacro.

If that is the case, then the mumbo-jumbo you need is:

    (defmacro deffrob (head tail)
      `(progn (defmacro behead (x)
		`(setf ,',head ,x))
	      (defmacro betail (y)
		`(setf ,',tail ,y))))

as any well-seasoned Common Lisp macrohacker can attest.

Your example expands the test case into:

	(defmacro behead (x) `(SETF ,(car x) ,x))
	(defmacro betail (y) `(SETF ,(cdr x) ,y))

which not only has the unfortunate property of allowing the 'x' of the
'(car x)' to be captured by the argument variable of 'behead', but it 
also causes the expansion of 'betail' to make an "apparent free reference" 
to 'x', which might or might not be captured by the surrounding context 
[recall the non-hygienic rules for Common Lisp.]

Of course, there is a place for  ,,  but it certainly isn't hygienic!

The Backquote Doctor's rule of thumb is:

     When there is doubly-nested backquotes, try out  ,',  first, and
     if that fails, then try out  ',',  second [by try out, I mean: 
     "When in doubt, macroexpand it out" and look at the resulting
     Common Lisp code; and if necessary partially evaluate the resulting
     code one or more levels.]

The second rule of thumb is: 

    Don't even bother trying to explain the reasoning behind it to anyone 
    else; they'll soon realize you are just talking to yourself . .   So,
    "when in doubt, macroexpand it out . . . "

Just to attest to the utility and expressivity of CL's backquote, I offer
this recent addition to the Lucid Common Lisp sources, as the final part of
the code which expands the interpreter's version of the macro for THE:

      `(destructuring-bind ,lambda-list (multiple-value-list ,form)
         (values-list `(,,@required-forms ,@,@optional-forms)))

[And I kid thee not.  This is real stuff; and some of us actually think
we understand it what it means . . .]

-- JonL --