multiple evaluation in macros

Discussion of Common Lisp
Post Reply
lrodrig
Posts: 17
Joined: Thu Sep 16, 2010 4:52 pm

multiple evaluation in macros

Post by lrodrig » Sat Jun 04, 2011 9:46 am

Hi,

I'm trying to implement a macro that creates both a struct and a function. The following code template:

Code: Select all

(defmacro macro-example (...)
  `(defstruct ...)
  `(defun  ....))
doesn't work since only the last element is actually evaluated and, therefore, the function is defined but the structure is not created. As a solution I could define a function that calls two macros: one for the function and another one for the struct but I was wondering if there is a way to do both things with just one macro. In other words, is it possible to generate two different pieces of code from one single macro?

Regards,
Luis.

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: multiple evaluation in macros

Post by edgar-rft » Sat Jun 04, 2011 10:04 am

Try this:

Code: Select all

(defmacro macro-example (...)
  `(progn
     (defstruct ...)
     (defun  ....)))
Any other construct using an implicit PROGN will work, too.

- edgar

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: multiple evaluation in macros

Post by ramarren » Sat Jun 04, 2011 10:46 am

edgar-rft wrote:Any other construct using an implicit PROGN will work, too.
Although do note that top level PROGN is specified to preserved top-levelness of forms, while other forms are not. This is usually not critical, but can affect compilation in ways which I never investigated in detail, but it is best avoided.

lrodrig
Posts: 17
Joined: Thu Sep 16, 2010 4:52 pm

Re: multiple evaluation in macros

Post by lrodrig » Sat Jun 04, 2011 12:42 pm

edgar-rft wrote:Try this:

Code: Select all

(defmacro macro-example (...)
  `(progn
     (defstruct ...)
     (defun  ....)))
Any other construct using an implicit PROGN will work, too.

- edgar
Thank you. I should have come up with this straightforward solution.

Regards,
Luiw

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: multiple evaluation in macros

Post by edgar-rft » Sun Jun 05, 2011 1:17 am

Edgar: Any other construct using an implicit PROGN will work, too.

Ramarren: Although do note that top level PROGN is specified to preserved top-levelness of forms, while other forms are not. This is usually not critical, but can affect compilation in ways which I never investigated in detail, but it is best avoided.
It's correct that PROGN is only guarateed to evaluate forms at the top-level if called at the top-level, so it's not guaranteed 100% for sure that code like this will work:

Code: Select all

(defmacro macro-example (...)
  ;; some heavily nested Lisp forms, where
  ;; PROGN is called deep inside the nesting
  `(foo ...
     (bar ...
       (baz ...
         (progn
           (defstruct ...)
           (defun  ....))))))
Like Ramarren I have not investigated in really deep detail so far if this may cause problems in compiled code, but AFAIK both DEFSTRUCT as well as DEFUN are defined to manipulate symbols in the global and not in the lexical environment.

Counter-example: If DEFUN is called e.g. inside a LET scope like in this standard closure example, then the variable X inside the DEFUN will be of course clearly affected by the surrounding LET binding:

Code: Select all

CL-USER> (defmacro macro-example ()
           `(let ((x 1))
              (defun add-x (arg) (+ arg x))))
MACRO-EXAMPLE

CL-USER> (macro-example)
ADD-X

CL-USER> (add-x 1)
2
Similar effects can easily happen if you don't mind the lexical environment where DEFSTRUCT or DEFUN are called.

- edgar

Post Reply