On May 4, 2016, at 6:08 PM, Johannes <[email protected]> wrote: > okay, but why does the following work without quotation? > user> (def f- (let [v 1 > f (fn [x] x)] f)) > ;; => #'user/f- > user> (eval {:d f-}) > ;; => {:d #function[user/fn--14679/f--14680]} > user> > > The problem is that the place in my program where I give the map containing > the function object to eval, the map cannot be quoted.
Hmm, I thought I had read “eval doesn’t accept function objects” in a couple places on the Internet, but when I checked this page: http://clojure.org/reference/evaluation I found the sentence "Any object other than those discussed above will evaluate to itself.” So, it appears to be a bug, either in the documentation or in eval. I’m only a Clojure noob, having started four weeks ago. so we’ll both have to wait for a more authoritative explanation from someone more familiar with Clojure internals. The reason I know about this (or thought I did) is because I recently struggled with a similar problem: dynamically supplying a method map to extend a protocol to a record. My solution was to define a top-level dynamically rebindable symbol and refer to it inside the expression passed to eval, something like this (untested code): (def ^:dynamic method-map-holder) (def dynamic-def-record [record-sym fields-vector method-map] (binding [method-map-holder method-map] (eval `(defrecord ~record-sym ~fields-vector)) (eval `(extend ~record-sym ~'my-project.core/MyProtocol method-map-holder)))) The trick is to call binding to put the method-map (containing function objects) into a place where eval can see it. That place is: bound to a top-level symbol, which also appears in the object passed to eval. Note that inside the ` form passed to eval, method-map-holder is not preceded by a tilde. eval will see that exact symbol (qualified by the enclosing namespace). The point of all this is to avoid evaluating the map before passing it to eval. Be aware that the above is an ugly hack, and probably not the best way to do it. I showed my actual code to someone with years of Clojure experience, and he immediately said, “Calling eval is a code smell: there’s almost always a better way to do what you’re trying to do,” and we quickly found a likely way to do what I needed with a macro. However, we did not find a way around temporarily binding the method-map to a dynamically rebindable symbol. -- Ben Kovitz http://mypage.iu.edu/~bkovitz/ -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
