Page 1 of 1
multiple evaluation in macros
Posted: Sat Jun 04, 2011 9:46 am
by lrodrig
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.
Re: multiple evaluation in macros
Posted: Sat Jun 04, 2011 10:04 am
by edgar-rft
Try this:
Code: Select all
(defmacro macro-example (...)
`(progn
(defstruct ...)
(defun ....)))
Any other construct using an implicit
PROGN will work, too.
- edgar
Re: multiple evaluation in macros
Posted: Sat Jun 04, 2011 10:46 am
by ramarren
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.
Re: multiple evaluation in macros
Posted: Sat Jun 04, 2011 12:42 pm
by lrodrig
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
Re: multiple evaluation in macros
Posted: Sun Jun 05, 2011 1:17 am
by edgar-rft
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