views:

187

answers:

3

How can I fix the simple macro foo in (elisp)Eval During Expansion?

None of the followings work:

(defmacro foo1 (a)
  `(setq (eval ,a) t))

(defmacro foo2 (a)
  `(setq ,(eval a) t))

(defmacro foo3 (a)
  `(setq ,a t))

I really don't get what's said in (elisp)Eval During Expansion. I think if I got it, I'd have been able to fix the macro.

Update: huaiyuan's solution works:

(defmacro foo7 (a)
  `(set ,a t))

(setq x 'b 
      a 'c)

(foo7 x)
(assert (eq b t))
(assert (eq x 'b))

(foo7 a)
(assert (eq a 'c))
(assert (eq c t))

(macroexpand '(foo7 x)) ; ==> (set x t)
(macroexpand '(foo7 a)) ; ==> (set a t)
A: 

What do you mean, "fix" ?

The page you are referring to shows that the macro works only if you call it with a name that is not the same name as the macro parameter. To fix the issue in question, either modify the macro to reduce the conflict opportunities, or the usages so that it does not conflict.

 (defmacro foo (aVeryLongAndImprobablyConflictingName)
   (list 'setq (eval aVeryLongAndImprobablyConflictingName) t))
Bahbar
A: 

The "right" fix is to not require evaluation of user-supplied parameters within the macro expansion function.

(defmacro foo4 (a) `(setq ,a t))

Though this does NOT do the same thing as either of foo1, foo2 or foo3. What is the problem you are trying to solve?

Vatine
Your foo4 looks the same as foo3.
RamyenHead
So it does! I even looked for that!
Vatine
+1  A: 

Try

(defmacro foo7 (a)
  `(set ,a t))

The semantics of elisp is often accidental to the implementation. For an example of well thought out, clearly specified macro systems, I recommend Common Lisp's.

huaiyuan