Reputation: 4276
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
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