1

I am trying to make a macro that creates a function that takes S-expresions and evaluates them inside the lexical context of the fixture. Here is the macro I wrote:

(defmacro def-fixture (name bindings)
  "Return a function that takes the form to execute but is wrapped between a let of the bindings"
  `(defun ,(intern (symbol-name name)) (body)
     (let (,bindings)
       (unwind-protect
           (progn
             body)))))

But when I run it it appears to be executing outside the lexical context I provided

(def-fixture test-fixture '(zxvf 1))

(test-fixture '(= zxvf 1))
let: Symbol's value as variable is void: zxvf

Btw, I have enabled the variable lexical binding. Any ideas as to what is my mistake?

PuercoPop
  • 6,707
  • 4
  • 30
  • 40

2 Answers2

2

This has nothing to do with lexical scoping. Your macro call expands to:

(defun test-fixture (body)
  (let ((quote (zxvf 1)))
    (unwind-protect (progn body))))

Which is of course not what you intended. I do not believe that (test-fixture '(= zxvf 1)) signals the error you cite (i.e. variable is void). Instead, the call signals (void-function zxvf) because it tries to evaluate (zxvf 1). The (= zxvf 1) expression is never evaluated, since it's quoted.

You might like to try something more like:

(defmacro def-fixture (name bindings)
  "Return a macro that takes the form to execute but is wrapped between a let of the bindings"
  `(defmacro ,name (body)
     `(let (,',bindings)
        (unwind-protect
          (progn
            ,body)))))

and then use it as in:

(def-fixture test-fixture (zxvf 1))
(test-fixture (= zxvf 1))
Stefan
  • 27,908
  • 4
  • 53
  • 82
1

The following note is in the emacs manual:

Also, the code in the body of a defun or defmacro cannot refer to surrounding lexical variables.

It might be what your problem is.

Also I do not know if you need to quote the second argument of def-fixture. I used the macrostep package to inspect the resulting macro and the result seems better without the quote.

Nicolas Dudebout
  • 9,172
  • 2
  • 34
  • 43