gensym's behavior in a macro

Discussion of Common Lisp
Post Reply
megera
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

gensym's behavior in a macro

Post by megera » Sun Dec 02, 2012 6:46 am

HI
I have a fast & easy question(easy for You ) about gensym used in that macro example:

Code: Select all

(defmacro for (var start stop &body body)
	   (let ((gstop (gensym)))
	     `(do ((,var ,start (1+ ,var))
		        (,gstop ,stop))
		       ((> ,var ,gstop))
		   ,@body)))

>(for x 1 5 (princ  x)))
12345
NIL   
But if I redefine ‘do test ‘as : (> ,var ,stop) instead of (> ,var ,gstop) for demonstration purposes only:

Code: Select all

(defmacro for (var start stop &body body)
	   (let ((gstop (gensym)))
	     `(do ((,var ,start (1+ ,var))
		        (,gstop ,stop))
		       ((> ,var ,stop))  ;; here
		     ,@body)))

;;why macro call:
(for x 1 5 (princ  x)))  ; return only -> NIL?
if I see it expanded:
(pprint (macroexpand-1 '(for x 1 5 (princ x)))) return -> (DO ((X 1 (1+ X))) ((> X 5)) (PRINC X))

it should work equally…..???why “do body” is not valued? Only because gensym’s variable is unused?? :?
thanks in advance!

Goheeca
Posts: 271
Joined: Thu May 10, 2012 12:54 pm
Contact:

Re: gensym's behavior in a macro

Post by Goheeca » Sun Dec 02, 2012 7:15 am

I get the same output + a warning about an unused variable, but it doesn't work equally. Look at this:

Code: Select all

(defmacro for (var start stop &body body)
  `(do ((,var ,start (1+ ,var))
        (stop-cond ,stop))
       ((> ,var stop-cond))
     ,@body))
stop will be evaluated only once and the result will be saved into the stop-cond, but we've captured stop-cond (we can't reach hypotetical outer stop-cond defined in let which is wrapping our for), hence we create gstop which its value is a unique generated symbol and unquote it at appropriate places where stop-cond was used.
Last edited by Goheeca on Sun Dec 02, 2012 8:10 am, edited 1 time in total.
cl-2dsyntax is my attempt to create a Python-like reader. My mirror of CLHS (and the dark themed version). Temporary mirrors of aferomentioned: CLHS and a dark version.

megera
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

Re: gensym's behavior in a macro

Post by megera » Sun Dec 02, 2012 8:05 am

HI Goheeca and thankf for your help!
Ok I understand reason to use gensym in macro , but yet it is not clear to me why using *,stop* instead *gstop*(gensym variable) in *do* test conditions return NIL..
For example You said that *,stop* will be evaluated only once, but if I ridefine *for* macro in this way and without use gensym expr, it’ll works as I expect:

Code: Select all

(defmacro for (var start stop &body body)
	     `(do ((,var ,start (1+ ,var)))
		       ((> ,var ,stop))
		      (progn
		         ,@body
		         (princ ,stop)))) 

1525354555
NIL
now ,stop will be evalutated for each iteration….but why if I define a gensym var this does not happen??? :? :?
thanks again for your patience.. :mrgreen:

Goheeca
Posts: 271
Joined: Thu May 10, 2012 12:54 pm
Contact:

Re: gensym's behavior in a macro

Post by Goheeca » Sun Dec 02, 2012 8:27 am

I've get this:

Code: Select all

* (defmacro for (var start stop &body body)
     (let ((gstop (gensym)))
         `(do ((,var ,start (1+ ,var))
               (,gstop ,stop))
              ((> ,var ,stop))
            ,@body)))

FOR
* (for x 1 5 (princ x))
; in: FOR X
;     (LET ((X 1) (#:G741 5))
;       (TAGBODY
;         (GO #:G743)
;        #:G742
;         (TAGBODY (PRINC X))
;         (PSETQ X (1+ X))
;        #:G743
;         (UNLESS (> X 5) (GO #:G742))
;         (RETURN-FROM NIL (PROGN))))
; 
; caught STYLE-WARNING:
;   The variable #:G741 is defined but never used.
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition
12345
NIL
* (dribble)
you can see that it works. That returned nil is a value of result-form which was omitted in this case.
cl-2dsyntax is my attempt to create a Python-like reader. My mirror of CLHS (and the dark themed version). Temporary mirrors of aferomentioned: CLHS and a dark version.

megera
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

Re: gensym's behavior in a macro

Post by megera » Sun Dec 02, 2012 8:41 am

THANKS!! :D

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: gensym's behavior in a macro

Post by pjstirling » Mon Dec 03, 2012 2:15 pm

When you have a misbehaving macro you should use MACROEXPAND to see that it is expanding to what you want it to. If you use emacs+slime, then you can put the cursor at the opening paren of the form and then typing C-c return

megera
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

Re: gensym's behavior in a macro

Post by megera » Tue Dec 04, 2012 3:50 am

Thanks pjstirling ;)

Post Reply