Jim Garrison
Jim Garrison

Reputation: 4276

Clojure eval error

Using Clojure 1.2, this code works

(defn A [] (fn [a] (+ a 2)))
(println ((A) 0))
(println (eval (list (A) 0)))

but the following code fails on the third line

(defn A [b] (fn [a] (+ a b)))
(println ((A 3) 0))
(println (eval (list (A 3) 0)))

Why?

Upvotes: 4

Views: 139

Answers (1)

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91534

Calling (list (A 3)) returns a function in a list:

user> (list (A 3) 0)
(#<user$A$fn__2934 user$A$fn__2934@2f09b4cb> 0)

eval expects to get a symbol in a list and it was getting the function it's self. if you quote the call to (A 3) then you will get the result you seek

user> (println (eval (list '(A 3) 0)))
3
nil

Part of this code is being evaluated before the call to eval and then eval is evaluating the rest. It is more common to se eval used on quoted forms with perhaps a term or to selectively unquoted (~).

user> (eval '((A 3) 0))
3

or

user> (def my-number 3)
#'user/my-number
user> (eval `((A ~my-number) 0))
3

edit: on the question of why it works with zero args and fails with one arg:

it seems that both forms work if you don't store them in vars (ie define them with defn) and instead manually inline them:

user> (def A (fn [b] (fn [a] (+ a b))))
#'user/A
user> (eval (list (A 3) 0))
; Evaluation aborted.
user> (eval (list (fn [b] (fn [a] (+ a b)) 3) 0))
3

Upvotes: 3

Related Questions