I'm doing a small project just for fun, and I added eval
support for it to make debug easier. But later I found a problem:
(let ((x 1))
(eval (1+ x)))
(defun foo (x form)
(eval form))
(foo 1 '(1+ x))
Code above won't work. Could someone please explain why and how to work it around? Thanks very much.
First, though
(let ((x 1))
(eval (1+ x)))
may look like it does work (it certainly does something), it is likely not doing, what you intend it to do. eval
is a regular function, so it receives its arguments evaluated by the caller. Effectively, you are calling eval
with an integer value of 2
-- which is then "evaluated" (since integers are self-quoting) to a result value of 2
.
In
(defun foo (x form)
(eval form))
it's easier to diagnose the failure. Run-time lexical bindings are not first-class objects, but something maintained by the interpreter/compiler behind the scenes. Regular functions (like eval
) cannot access lexical variables defined at their call-sites.
One work-around would be to use special variables:
(defun foo (x form)
(declare (special x))
(eval form))
The declaration tells your lisp implementation, that x
should be dynamically bound within its scope.