This is another case of function-object evaluation acting hinky, actually. Specifically, (eval (id 7)) is evaluating a list of (id 7), not ('id 7). As near as I can figure out, rather than embed the function object reference into the code OR complain, it is creating a new instance of its class with newInstance, more or less in the manner I suggested in another thread recently -- the failure with closures happening because it doesn't check for closures and closures don't have a public no-argument constructor, so need special handling (and preservation of the arguments they were constructed with -- the closed-over values).
A longer-term fix might be to make instances of the function superclass generated by (fn [foo] bar) (but not all IFns!) compare equal if their exact classes are equal and, in the case that they are closures, the closed-over values compare equal. This doesn't break the expected semantics that functions that behave differently should compare UNequal, but allows functions to be represented as constructor calls to their classes and then reconstructed without breaking equality. In particular, we don't need to use eval to get hinky function equality semantics already: user=> (defn fn-maker1 [] (fn [] 3)) #'user/fn-maker1 user=> (= (fn-maker1) (fn-maker1)) false user=> (defn fn-maker2 [x] (fn [] x)) #'user/fn-maker2 user=> (= (fn-maker2 3) (fn-maker2 3)) false user=> (= (fn-maker2 3) (fn-maker2 4)) false user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y))) #'user/fn-maker3 user=> (= (fn-maker3 1 2) (fn-maker3 1 2)) false user=> (= (fn-maker3 1 2) (fn-maker3 2 1)) false Ideally, the results would be this instead: user=> (defn fn-maker1 [] (fn [] 3)) #'user/fn-maker1 user=> (= (fn-maker1) (fn-maker1)) true ; conceptually identical functions user=> (defn fn-maker2 [x] (fn [] x)) #'user/fn-maker2 user=> (= (fn-maker2 3) (fn-maker2 3)) true ; conceptually identical functions user=> (= (fn-maker2 3) (fn-maker2 4)) false ; genuinely not the same user=> (defn fn-maker3 [x y] (fn [z] (+ (* z x) y))) #'user/fn-maker3 user=> (= (fn-maker3 1 2) (fn-maker3 1 2)) true ; conceptually identical functions user=> (= (fn-maker3 1 2) (fn-maker3 2 1)) false ; not the same: user=> ((fn-maker3 1 2) 10) 12 user=> ((fn-maker3 2 1) 10) 21 Now, fn-maker3 could have produced (fn [z] (+ x y z)) in which the roles of x and y are symmetrical, but I don't think it reasonable to expect the compiler to detect every situation in which distinct closed-over values give identically-behaved functions (in fact that's probably equivalent to the halting problem) so I'd consider it reasonable for it to consider closures unequal if they have distinct sequences of closed-over values (and I say "sequences" here because as fn-maker3 shows they aren't generally interchangeable; the constructor for fn-maker3's closure's class will have some particular order it takes them in and as sequences in that order they'd have to be equal for two fn-maker3 results to be treated as equal here). -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en