Reputation: 58826
I have the following defined in clojure:
(def ax '(fn x [] (+ 1 z)))
(let [z 4]
(str (eval ax))
)
:but instead of returning :
5
: I get :
Unable to resolve symbol: z in this context
: I have tried changing "let" to "binding" but this still does not work. Does anyone know what is wrong here?
Upvotes: 4
Views: 318
Reputation: 4203
Making the smallest possible changes to your code to get it to work:
(def ^:dynamic z nil)
(def ax '(fn x [] (+ 1 z)))
(binding [z 4]
(str ((eval ax)))
)
The two changes are defining z as a dynamic var, so that the name resolves, and putting another paren around (eval ax), because ax is returning a function.
A little bit nicer is to change the definition of ax:
(def ^:dynamic z nil)
(def ax '(+ 1 z))
(binding [z 4]
(str (eval ax))
)
So evaluating ax immediately gets the result you want, rather than returning a function that does it.
Nicer again is to skip the eval:
(def ^:dynamic z nil)
(defn ax [] (+ 1 z))
(binding [z 5]
(str (ax))
)
But best of all is to not have z floating around as a var, and pass it in to ax as Mimsbrunnr and Joost suggested.
Upvotes: 11
Reputation: 32534
Right so I'm not entirely sure what you are trying to do here.
I mean this works, though it's not using eval it's defining x to be the function (fn [ x ] (+ x 1))
> (def x #(+ 1 %))
#'sandbox102711/x
> (x 4)
5
In the end, eval is not something you should be using. As a Lisp Cljoure's support for lambda abstraction and macros ( see the fn definition above ) should remove the need.
Upvotes: 1
Reputation: 17761
The short answer is don't use eval. You almost never need to, and certainly not here.
For example:
user> (defn ax [z]
(+ 1 z))
#'user/ax
user> (let [f #(ax 4)]
(f))
5
Upvotes: 8