From: Maurice
Subject: problem with compiled macro
Date: 
Message-ID: <cv2vpg$g6q$01$1@news.t-online.com>
Hi,

the following sample-code demonstrates my problem:

*** file: one.lisp ***

    (defparameter *msg* nil)

    (defmacro show-message ()
      `(print ,*msg*))

*** file: two.lisp ***

    (let ((*msg* "hello"))
      (show-message))

Now if I compile those files and load the second one it prints me NIL.
The value of *msg* seems to be taken at compile-time.

Is there a way to make the macro taking the new value of *msg*?

I'm using clisp.

Thank you in advance.

From: Kaz Kylheku
Subject: Re: problem with compiled macro
Date: 
Message-ID: <1108700285.718143.162060@f14g2000cwb.googlegroups.com>
Maurice wrote:
> Hi,
>
> the following sample-code demonstrates my problem:
>
> *** file: one.lisp ***
>
>     (defparameter *msg* nil)
>
>     (defmacro show-message ()
>       `(print ,*msg*))
>
> *** file: two.lisp ***
>
>     (let ((*msg* "hello"))
>       (show-message))
>
> Now if I compile those files and load the second one it prints me
NIL.

You have to load the first one also, because that's where *MSG* is
defined.

The compiled image of the second one won't have the definition of
*MSG*, even though the SHOW-MESSAGE macro from the first file was used
in compiling the second.

> The value of *msg* seems to be taken at compile-time.

It's certainly taken at macro-expansion time, because that's when the
backquote expression is evaluated, causing the value of *MSG* to be
substituted into the template, and the resulting object embedded as
source code into the macro expansion site.

> Is there a way to make the macro taking the new value of *msg*?

I think you are looking for this:

  (defmacro show-message ()
    '(print *msg*))  ;; regular quote

All you want is the macro to produce an expression that calls for the
evaluation of the *MSG* symbol as a variable, right?
From: Adam Warner
Subject: Re: problem with compiled macro
Date: 
Message-ID: <pan.2005.02.17.20.58.14.284562@consulting.net.nz>
On Thu, 17 Feb 2005 21:45:38 +0100, Maurice wrote:

> Hi,
> 
> the following sample-code demonstrates my problem:
> 
> *** file: one.lisp ***
> 
>     (defparameter *msg* nil)
> 
>     (defmacro show-message ()
>       `(print ,*msg*))
> 
> *** file: two.lisp ***
> 
>     (let ((*msg* "hello"))
>       (show-message))

Maurice, after macroexpansion you have this code to be evaluated:

(let ((*msg "hello"))
  (print nil))

If you want to substitute the expression (print *msg*) into your code then
quote it:

(defmacro show-message ()
  '(print *msg*))

(macroexpand-1 '(show-message)) => (PRINT *MSG*)

A function may also be appropriate:

(defun show-message ()
  (print *msg*))

Regards,
Adam
From: Maurice
Subject: Re: problem with compiled macro
Date: 
Message-ID: <cv31n2$g6q$01$2@news.t-online.com>
Hi,

Adam Warner <······@consulting.net.nz> wrote:
> Maurice, after macroexpansion you have this code to be evaluated:
> 
> (let ((*msg "hello"))
>   (print nil))

yes, I noticed that. But this is only when I compile those files
separatly. For example this works as intended:

  [1]> (defparameter *msg* nil)
  *MSG*
  [2]> (defmacro show-message () `(print ,*msg*))
  SHOW-MESSAGE
  [3]> (let ((*msg* "Hello")) (show-message))
  "Hello" 
  "Hello"

> If you want to substitute the expression (print *msg*) into your code then
> quote it:
> 
> (defmacro show-message ()
>   '(print *msg*))
> 
> (macroexpand-1 '(show-message)) => (PRINT *MSG*)

hm, no, thats not what I want.

> A function may also be appropriate:

yes of course, but only for this example. In my code I really need a
macro.
From: David Sletten
Subject: Re: problem with compiled macro
Date: 
Message-ID: <m68Rd.12389$xX3.5276@twister.socal.rr.com>
Maurice wrote:

> Hi,
> 
> Adam Warner <······@consulting.net.nz> wrote:
> 
>>Maurice, after macroexpansion you have this code to be evaluated:
>>
>>(let ((*msg "hello"))
>>  (print nil))
> 
> 
> yes, I noticed that. But this is only when I compile those files
> separatly. For example this works as intended:
> 
>   [1]> (defparameter *msg* nil)
>   *MSG*
>   [2]> (defmacro show-message () `(print ,*msg*))
>   SHOW-MESSAGE
>   [3]> (let ((*msg* "Hello")) (show-message))
>   "Hello" 
>   "Hello"
> 
> 
>>If you want to substitute the expression (print *msg*) into your code then
>>quote it:
>>
>>(defmacro show-message ()
>>  '(print *msg*))
>>
>>(macroexpand-1 '(show-message)) => (PRINT *MSG*)
> 
> 
> hm, no, thats not what I want.
> 
> 
>>A function may also be appropriate:
> 
> 
> yes of course, but only for this example. In my code I really need a
> macro.
I don't have the full answer to your question, but I think it has 
something to do with compilation (as your subject line suggests...). 
SBCL and OpenMCL have a compiler behind their REPL, so everything gets 
compiled, whereas CLISP's REPL is interpreted by default. SBCL and 
OpenMCL output NIL using your example above. This is the same result you 
get when you compile your file in CLISP.

David Sletten
From: Adam Warner
Subject: Re: problem with compiled macro
Date: 
Message-ID: <pan.2005.02.17.21.45.17.192151@consulting.net.nz>
On Thu, 17 Feb 2005 22:18:28 +0100, Maurice wrote:

> yes, I noticed that. But this is only when I compile those files
> separately. For example this works as intended:
> 
>   [1]> (defparameter *msg* nil)
>   *MSG*
>   [2]> (defmacro show-message () `(print ,*msg*))
>   SHOW-MESSAGE
>   [3]> (let ((*msg* "Hello")) (show-message))
>   "Hello" 
>   "Hello"

Well then you got lucky. Don't rely upon quirks in the CLISP interpreter.
This can only work if show-message is macroexpanded _after_ *msg* is bound
to "Hello". Macros are usually expanded well before code is evaluated at
run time (at macroexpansion time, which may be weeks before someone
even runs the program).

>> If you want to substitute the expression (print *msg*) into your code
>> then quote it:
>> 
>> (defmacro show-message ()
>>   '(print *msg*))
>> 
>> (macroexpand-1 '(show-message)) => (PRINT *MSG*)
> 
> hm, no, thats not what I want.

Then I don't believe you sufficiently understand what you want.
 
>> A function may also be appropriate:
> 
> yes of course, but only for this example. In my code I really need a
> macro.

In this example you clearly do not:

[1]> (defparameter *msg* nil)
*MSG*
[2]> (defun show-message () (print *msg*))
SHOW-MESSAGE
[3]> (let ((*msg* "Hello")) (show-message))

"Hello"
"Hello"

Regards,
Adam
From: Adam Warner
Subject: Re: problem with compiled macro
Date: 
Message-ID: <pan.2005.02.17.21.50.16.929731@consulting.net.nz>
On Thu, 17 Feb 2005 22:18:28 +0100, Maurice wrote:

>> A function may also be appropriate:
> 
> yes of course, but only for this example. In my code I really need a
> macro.

Then let's see a relevant example! If you're yet to grok the different
stages of evaluation (read time, macroexpansion time, compile time, run
time) then you may have overlooked a more appropriate solution.

Regards,
Adam
From: Maurice
Subject: Re: problem with compiled macro
Date: 
Message-ID: <cv39n1$s7d$01$1@news.t-online.com>
Adam Warner <······@consulting.net.nz> wrote:
> On Thu, 17 Feb 2005 22:18:28 +0100, Maurice wrote:
> 
> >> A function may also be appropriate:
> > 
> > yes of course, but only for this example. In my code I really need a
> > macro.
> 
> Then let's see a relevant example! If you're yet to grok the different
> stages of evaluation (read time, macroexpansion time, compile time, run
> time) then you may have overlooked a more appropriate solution.

Hi,

Now I found another solution :-)

My goal was to simplify the clisp ffi-interface a bit.
Normaly it looks like that:

  (def-call-out my-func
    (:name "my_func")
    (:library "./libfoo.so")
    (:language :stdc)
    (:arguments (a int) (b c-string))
    (:return-type float))

I made a macro so I only need to write:

  (def-cfun float my-func (int c-string))

This would be general applicable except the name of the library
"libfoo.so" was hardcoded.

My attempt to solve this situation was the global variable I called
*msg* in my example. Clisp's behaviour made me think this is possible.
Thank you for the clarification.

Just for the sake of completeness, here is my new solution:

  (defmacro def-cfun (library-name return-type name args)
    `(def-call-out ,name
      (:library ,library-name)
      ...))

  (defmacro with-import-from-library ((filename) &rest prototypes)
    `(progn
      ,@(mapcar (lambda (p) `(def-cfun ,filename ,@p)) prototypes)))

and finally:

  (with-import-from-library ("libfoo.so")
    (float my-func (int c-string))
    ...
    )

Thanks.
Maurice