avoiding eval in a macro

Discussion of Common Lisp

avoiding eval in a macro

Postby murphey607 » Fri Jan 06, 2012 1:09 pm

Hi there,

I'm not very deep into CL yet and struggling with this problem:
The following macro won't compile because ,@body is not a list (sbcl)
However if try a (listp ,body) it will return true. Can you please help me to understand this?
(the code is reduced beyond usefulness to show the problem)

TIA
murph

Code: Select all
(defmacro gen-name-broken (name)
  (let ((body (intern "BODY")))
    `(defmacro ,name (&body body)
       (let ((result (progn ,@body)))
    result))))



Of course I can use eval like this, but I want to avoid it
Code: Select all

(defmacro gen-name-eval (name)
  (let ((body (intern "BODY")))
    `(defmacro ,name (&body body)
       (warn "is-list? ~S~%" (listp ,body))
       (let ((result (apply #'eval ,body)))
    result))))
murphey607
 
Posts: 2
Joined: Fri Jan 06, 2012 12:48 pm

Re: avoiding eval in a macro

Postby Ramarren » Fri Jan 06, 2012 2:42 pm

murphey607 wrote:I'm not very deep into CL yet and struggling with this problem:


You probably shouldn't be nesting DEFMACRO then. Or ever, nesting macro definitions generally and definitely directly is not really a good idea, because keeping track of scope is difficult.

In your case the variable body in the scope of the outer macro is not a list, it has a value of a single symbol created by INTERN. The LISTP in the second example is in the scope of the inner macro, which is a list because it refers to the argument of the inner macro.
Ramarren
 
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland

Re: avoiding eval in a macro

Postby virex » Tue Jan 10, 2012 3:00 pm

The problem isn't scoping, it's that your backquoting levels aren't in order. The inner defmacro is inside a single backquote, so the call to ,@body is going to look for body outside of that backquote level and it finds a symbol, not a list (because that's what you introduced with intern). But the call that checks if body is a list is within the backquotes and thus sees the new definition of body, which is indeed a list. This means that you need to move that backquote around or add another one to get the thing to compile.
virex
 
Posts: 17
Joined: Fri Oct 28, 2011 3:41 pm

Re: avoiding eval in a macro

Postby murphey607 » Sat Jan 21, 2012 5:28 am

Hi,
I was able to get behind my problem by changing the line
Code: Select all
  (let ((body (intern "BODY")))

to
Code: Select all
  (let ((body (intern "FOO")))


this made it possible to get different error-messages for the body variable depending on the backquote level

thanks for your help

greetings

murphy
murphey607
 
Posts: 2
Joined: Fri Jan 06, 2012 12:48 pm


Return to Common Lisp

Who is online

Users browsing this forum: Google [Bot] and 4 guests