From: Raja Ramachandran
Subject: dynamic bindings and macros
Date: 
Message-ID: <fnl6vl$oc0$1@aioe.org>
Hello -

Can someone help me understand this please:


* (defvar *val* 1)
* (defmacro test ()
           `(progn
             (format t "===>~f~%" (1+ ,*val*))))

* (test)
===>2.0

* (let ((*val* 100))
      (test))
===>2.0


1) Why is this not 101? 
2) How can I get it to be 101?
3) And what is the difference between the form above and this:

* (let ((*val* 100))
           (macroexpand-1 '(test)))

(PROGN (FORMAT T "===>~f~%" (1+ 100)))


I've rewritten my original macro as a function (which is what it should've
been), but I'm curious as to how to make it work.

Thank you.
Raja

P.S - No, I'm not trying to use a macro to increment a number. I just wanted
to post a simple example.

From: Thomas A. Russ
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <ymir6g1wgxa.fsf@blackcat.isi.edu>
Raja Ramachandran <········@iit.edu> writes:

> Hello -
> 
> Can someone help me understand this please:
> 
> 
> * (defvar *val* 1)
> * (defmacro test ()
>            `(progn
>              (format t "===>~f~%" (1+ ,*val*))))
                                        ^

The comma insures that whatever the value of *val* is when the macro is
expanded will be inserted into the code directly.


> * (test)
> ===>2.0
> 
> * (let ((*val* 100))
>       (test))
> ===>2.0

The macro is expanded BEFORE any of the resulting code is evaluated.
Furthermore, the macro expansion takes place before the let binding is
evaluated and therefore the binding doesn't affect the value at
macroexpansion time.  It only affects the value of *val* at evaluation
time.

So, in effect, you are evaluating the expression:

  (let ((*val* 100))
    (progn (format t "===>~f~%"(1+ 1))))

> 1) Why is this not 101? 
> 2) How can I get it to be 101?

One way would be to not put the comma in the macro expansion.  Then the
resulting code will refer to the value of the global symbol instead of
having the value of the symbol at macro expansion time place directly
into the code.

> 3) And what is the difference between the form above and this:
> 
> * (let ((*val* 100))
>            (macroexpand-1 '(test)))
> 
> (PROGN (FORMAT T "===>~f~%" (1+ 100)))

Now you are expanding the macro at evaluation time instead of
macro-expansion time.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Rainer Joswig
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <joswig-4DE524.19382028012008@news-europe.giganews.com>
In article <············@aioe.org>,
 Raja Ramachandran <········@iit.edu> wrote:

> Hello -
> 
> Can someone help me understand this please:
> 
> 
> * (defvar *val* 1)
> * (defmacro test ()
>            `(progn
>              (format t "===>~f~%" (1+ ,*val*))))
> 
> * (test)
> ===>2.0

(macroexpand '(test)) is what?

> 
> * (let ((*val* 100))
>       (test))
> ===>2.0

See above.

> 
> 
> 1) Why is this not 101? 
> 2) How can I get it to be 101?

(defmacro test ()
   '(progn
      (format t "===>~f~%" (1+ *val*))))

Try above.

> 3) And what is the difference between the form above and this:
> 
> * (let ((*val* 100))
>            (macroexpand-1 '(test)))
> 
> (PROGN (FORMAT T "===>~f~%" (1+ 100)))
> 
> 
> I've rewritten my original macro as a function (which is what it should've
> been), but I'm curious as to how to make it work.
> 
> Thank you.
> Raja
> 
> P.S - No, I'm not trying to use a macro to increment a number. I just wanted
> to post a simple example.
From: Raja R
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <fnlc3s$b5s$1@aioe.org>
Rainer Joswig wrote:

> (macroexpand '(test)) is what?

Thank you - that'll teach me to check the obvious cases before asking for
help!


Raja
From: Maciej Katafiasz
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <fnl8i0$ou9$2@news.net.uni-c.dk>
Den Mon, 28 Jan 2008 19:38:20 +0100 skrev Rainer Joswig:

I understand what and why happens, what you point out and why it makes 
sense, however I don't understand that part:

>> 3) And what is the difference between the form above and this:
>> 
>> * (let ((*val* 100))
>>            (macroexpand-1 '(test)))
>> 
>> (PROGN (FORMAT T "===>~f~%" (1+ 100)))

This should not have 100 in there.

Cheers,
Maciej
From: Pascal Bourguignon
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <873ashsq9d.fsf@thalassa.informatimago.com>
Maciej Katafiasz <········@gmail.com> writes:

> Den Mon, 28 Jan 2008 19:38:20 +0100 skrev Rainer Joswig:
>
> I understand what and why happens, what you point out and why it makes 
> sense, however I don't understand that part:
>
>>> 3) And what is the difference between the form above and this:
>>> 
>>> * (let ((*val* 100))
>>>            (macroexpand-1 '(test)))
>>> 
>>> (PROGN (FORMAT T "===>~f~%" (1+ 100)))
>
> This should not have 100 in there.

Then don't write what you wrote!

In anycase, it's not clear what you want to archieve. 



Macros are expanded at macroexpansion time, usually some time before
compilation.  If you wanted to ensure the variable *val* be accessible
in that environment, you'd have to write at least:

(eval-when (:compile-toplevel)
  (defvar *val* 100))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: Alan Crowe
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <86prvl1vsf.fsf@cawtech.freeserve.co.uk>
Raja Ramachandran <········@iit.edu> writes:

> Hello -
> 
> Can someone help me understand this please:
> 
> 
> * (defvar *val* 1)

DEFVAR checks to see if *VAL* is bound.
Finding it unbound, DEFVAR runs the initialisation form.
The form 1 gets evaluated, and its value, 1, gets stored
away for future use.
DEFVAR also proclaims the symbol *VAL* to be special.

> * (defmacro test ()
>            `(progn
>              (format t "===>~f~%" (1+ ,*val*))))

A macroexpansion function is created, something like

(lambda()
  (cons 'progn
        (list 'format t "===>~f~%" (list '1+ *val*))))

and stored away for future use.


> 
> * (test)

READ builds a list with one item, the symbol TEST

EVAL sets about evaluating the list
The macroexpansion function is asked to write some code.
You can see what it writes with macroexpand-1

    CL-USER> (macroexpand-1 '(test))

    (PROGN (FORMAT T "===>~f~%" (1+ 1)))
    T

EVAL executes the code, which prints ===>2.0 and evaluates
to NIL

PRINT prints NIL

> * (let ((*val* 100))
>       (test))

READ builds a list of three items, the symbol LET, the
binding, and the inner form.

EVAL sets about the list. The third item needs macroexpanding.
The macroexpansion function consults *VAR*, which is still
bound to 1, so it returns 
   (PROGN (FORMAT T "===>~f~%" (1+ 1))) 
just as before.

EVAL now has the fully expanded code

    (LET ((*VAL* 100))
      (PROGN (FORMAT T "===>~f~%" (1+ 1))))

It is too late the binding of *VAL* to affect the
macroexpansion, which has already been done. The code
behaves as before.

> * (let ((*val* 100))
>            (macroexpand-1 '(test)))
> 

READ builds a list of three items.

EVAL gets to work and remembers that MACROEXPAND-1 is a
function. So EVAL knows that the arguments are Common Lisp
code, which may need macroexpansion. The inner form is

    (macroexpand-1 (quote (test)))

so EVAL thinks about (quote (test)) EVAL likes QUOTE because
it can stop thinking. The stuff inside the quote is literal
data that is passed to the function, unevaluated.

EVAL now has the fully expanded code

    (let ((*val* 100))
      (macroexpand-1 '(test)))

EVAL binds *VAL* to 100 and calls MACROEXPAND-1 on the
little list (TEST). MACROEXPAND-1 finds the macroexpansion
function. The function needs the value of *VAL*. Since *VAL*
is special the most recent binding, to 100, takes precedence.
The macroexpansion is computed

    (PROGN (FORMAT T "===>~f~%" (1+ 100)))

The function macroexpand returns, the inner scope exits and
*VAL* returns to 1.


There is a gap in my understanding of Common Lisp. Must a
conforming EVAL macroexpand everything before it starts the
second stage of evaluation? I know from 3.2.2.2 Minimal
Compilation that compilation forces all macroexpansion, so
you can be sure that a conforming implementation will run
all the macroexpansion functions before run time and never
again. But some implementations have
interpreters. Presumably code typed in at the REPL could be
macroexpanded on the fly. In that case some implementations
will do

(let ((*var* 100)) (test)) => 2

while others, also conforming do

(let ((*var* 100)) (test)) => 101

Alan Crowe
Edinburgh
Scotland
From: Maciej Katafiasz
Subject: Re: dynamic bindings and macros
Date: 
Message-ID: <fnlj3k$ou9$3@news.net.uni-c.dk>
Den Mon, 28 Jan 2008 21:32:00 +0000 skrev Alan Crowe:

[a good and detailed explanation ]

Ah-ha! So I lied, I didn't actually understand what was happening, I had 
a wrong idea that took me far enough, looking like it was correct, but 
then failed on point 3. Thanks.

Cheers,
Maciej