Evaluate Macroform Arguments

What is the best practice for selectively passing evaluated arguments to macroscopic form?

To clarify: the usefulness of macros lies in its ability to receive an invaluable parameter, in contrast to the default evaluation rule for function forms. However, legitimate use cases exist to evaluate macro arguments.

Consider a far-fetched example:

(defparameter *func-body* '((print i) (+ i 1))) 

Suppose it would be nice that *func-body* can serve as the body of our-defun macro, which is defined as:

 (defmacro our-defun (fun args &body body) `(defun ,fun ,args ,@body)) 

So after (our-defun foo (i) (+ 1 i)) we could say (foo 1) to get 2 . However, if we use (our-defun foo (i) *func-body*) , the result (foo 1) will be ((PRINT I) (+ I 1)) (i.e. the value is *func-body* ). It would be nice if we could force *func-body* to be evaluated as an argument to our-defun macro.

Currently I can come up with a technique for using compile and funcall for this, as in

 (funcall (compile nil `(lambda () (our-defun foo (i) ,@*func-body*)))) 

after which (our-defun 1) prints 1 and returns 2 , as expected. I can come up with a case for doing this work with eval , but I would prefer to stay away from eval due to its features in scope.

This leads to my question at the beginning, is there an easier or native way to do this?

PS

An ill-conceived example is presented in the function (UPDATE-HOOK) , which uses two library macros (ADD-HOOK) and (REMOVE-HOOK) and it is necessary to evaluate its parameters. The technique used here is (funcall (compile nil `(lambda () ...))) .

 (defun update-hook (hook hook-name &optional code) (funcall (compile nil `(lambda () (remove-hook ,hook ',hook-name)))) (unless (null code) (compile hook-name `(lambda () ,@code)) (funcall (compile nil `(lambda () (add-hook ,hook ',hook-name)))))) 
+4
source share
2 answers

This is a bit confusing. The macro does not receive invaluable parameters.

The macro receives the source code and creates the source code. Remember also that the source code in Lisp is actually provided as data. A macro creates code that evaluates some forms and some not.

Macros must work in a compiling system. Before starting. At compile time. The entire macro sees the source code, and then it creates the source code. Think of macros as code transformations, rather than evaluating arguments or not.

It would be nice if we could force *func-body* to be evaluated as our-defun macro argument

It is not very clean. On a compiled system, you need to make sure that *func-body* really has a useful binding and that it can be resolved using the BROWSE TIME .

If you have a macro like DEFUN , it makes sense to put the source code. If you want to paste some source code into the form, then it might make sense to do this while reading:

 (defun foo (i) #.`(,@*foo*)) 

But I would usually like to avoid this code.

two library macros (ADD-HOOK) and (REMOVE-HOOK) and its parameters need to be evaluated.

Why should ADD-HOOK and REMOVE-HOOK be macros? Unless you have a real reason, they just have to be functions. Already since they make reuse difficult.

If you want to make ADD-HOOK and REMOVE-HOOK macros for some reason, then UPDATE-HOOK usually also be a macro.

+4
source

The list that you pass to your macro takes the form

 (Quote (...)) 

So the list you really want is the CADR of the list you get.

0
source

All Articles