Andreas Kostler <[email protected]> writes:
> Is this a 'bug' with eval?
No, eval is a simply a function and so like any other function it can't
"see" the lexical (local) environment which it was called from.
Doing this:
(let [a 1, b 2] (eval '(+ a b)))
Is similar to doing this:
(defn cake []
(+ a b))
(let [a 1, b 2] (cake))
Anyway, here's my take on a eval macro which captures the lexical
environment. It's similar to Ken's but avoids the need to explicitly
specify the environment.
First we need a version of eval which takes some let bindings. This is
straightforward, just wrap the form in a let statement:
(defn eval-let [bindings form]
(eval `(let [...@bindings] ~form)))
Note that's just a regular function again. We can use it like so:
(eval-let '[a 1, b 2] '(+ a b))
;; => 3
Next we need a way of getting at the lexical environment. Since 1.2
there's a nice supported way to do it. There's an implicit argument
passed to macros called &env. (keys &env) will get us a list of symbols
in the lexical environment, so:
(defmacro lexical-bindings []
(let [symbols (keys &env)
quoted-symbols (for [sym symbols] `(quote ~sym))]
(vec (interleave quoted-symbols symbols))))
What the heck does that do? Simple, if the environment contains
bindings 'a and 'b then it expands to the code ['a a 'b b].
Let's try it:
(let [a 1, b 2] (lexical-bindings))
;; => [b 2 a 1]
Perfect! That's actually all we need:
(let [a 1, b 2] (eval-let (lexical-bindings) '(+ a b)))
;; => 3
But for brevity we could define one last macro:
(defmacro lexeval [form]
`(eval-let (lexical-bindings) ~form))
And thus a version of eval which does what you're expecting:
(let [a 1, b 2] (lexeval '(+ a b)))
;; => 3
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en