gensym's behavior in a macro

Discussion of Common Lisp

gensym's behavior in a macro

Postby 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!
megera
 
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

Re: gensym's behavior in a macro

Postby 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).
User avatar
Goheeca
 
Posts: 213
Joined: Thu May 10, 2012 12:54 pm

Re: gensym's behavior in a macro

Postby 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:
megera
 
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm

Re: gensym's behavior in a macro

Postby 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).
User avatar
Goheeca
 
Posts: 213
Joined: Thu May 10, 2012 12:54 pm

Re: gensym's behavior in a macro

Postby megera » Sun Dec 02, 2012 8:41 am

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

Re: gensym's behavior in a macro

Postby 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
pjstirling
 
Posts: 79
Joined: Sun Nov 28, 2010 4:21 pm

Re: gensym's behavior in a macro

Postby megera » Tue Dec 04, 2012 3:50 am

Thanks pjstirling ;)
megera
 
Posts: 30
Joined: Wed Oct 10, 2012 1:34 pm


Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 3 guests

cron