Re: ONCE-ONLY



On Fri, 29 Apr 2005 17:27:35 +0200, Pascal Bourguignon <pjb@xxxxxxxxxxxxxxxxx> wrote:

[SKIP]
Unfortunately the use of anonymous gensyms doesn't help reading this.
Let's correct it:

[246]> (defmacro once-only ((&rest names) &body body)
     (let ((gensyms (loop for n in names collect (gensym (string n)))))
       `(let (,@(loop for g in gensyms collect `(,g (gensym ))))
	 `(let (,,@(loop for g in gensyms for n in names
		       collect ``(,,g ,,n)))
	    ,(let (,@(loop for n in names for g in gensyms
			 collect `(,n ,g)))
	       ,@body)))))
ONCE-ONLY
[41]> (macroexpand-1 '(once-only (a b)  (list 'list a b)))
(LET ((#:A4103 (GENSYM)) (#:B4104 (GENSYM)))
 (LIST 'LET (LIST (LIST #:A4103 A) (LIST #:B4104 B))
  (LET ((A #:A4103) (B #:B4104)) (LIST 'LIST A B)))) ;
T

Now we see that this macro expands to code that return a s-expression.

If you evaluate this s-expression you get what macros using once-only

This is probably the key of my misunderstanding. You say "If you evaluate this s-expression". Isn't this the job of the evaluator? This additional level of evaluation proved quite surprising for me. A macro produces output (a list), if this list's CAR isn't a macro the macroexpansion is done, no further processing is performed during macroexpansion time, right? ONCE-ONLY (from your example) expands to a list which doesn't contain macro name as its CAR(s). So at that moment macroexpansion stopped and so did I, unable to solve the puzzle. Where does this additional evaluation come from?

get.  To do that, we remove "#:", and we add templates for the
arguments A and B:

[47]> (let ((A :A-template) (b :b-template))
 (LET ((A4103 (GENSYM)) (B4104 (GENSYM)))
 (LIST 'LET (LIST (LIST A4103 A) (LIST B4104 B))
  (LET ((A A4103) (B B4104)) (LIST 'LIST A B)))))

(LET ((#:G4109 :A-TEMPLATE) (#:G4110 :B-TEMPLATE)) (LIST #:G4109 #:G4110))
[SKIP]
--
Vladimir Zolotykh
.



Relevant Pages

  • Re: Question about compilation/evaluation environments
    ... >> you started from a sexpr and interpreted it in that environment. ... In this case, the form is the macro function, ... If the compilation and evaluation environments are provably ... The macro expansion function is then run, ...
    (comp.lang.lisp)
  • Re: Newbie question: a function that returns an argument w/o evaluating it...
    ... of its formal argument) since all evaluation of argument forms occurs ... (DEFUN STACK-TOP MACRO (MACRO-FORM) ... which was called a displacing macro because after the first time you did ...
    (comp.lang.lisp)
  • Re: old school debugging
    ... time at the progn-like forms of the macro. ... initializing variables #:something and frob to nil, ... a macro form, you increase the macroexpansion level, and when you ... that if a little worse than perfection is better than perfection, ...
    (comp.lang.lisp)
  • Re: newbie Q: defmacro
    ... When you call a macro, the arguments are not evaluated like when you call ... the error message in this case, because MAPCAR needs a list there, not ... If you want COMPILE-MACHINE to operate on a list of data, ... I'm more interested in the parameter evaluation part. ...
    (comp.lang.lisp)
  • Re: old school debugging
    ... the expansion will be EQ to the form in the original macro ... the macroexpansion level, and when you leave a macroexpansion form, ... How do you relate the form (USER-FN) that appears in level 1 to the form ... both the call to FROB and the call to USER-FN. ...
    (comp.lang.lisp)