On Wed, May 4, 2011 at 8:01 PM, Ken Wesson <kwess...@gmail.com> wrote: > Note that instantiating the class with 4 gives us an add-4-to function > instead of the original add-3-to function here. To actually convert > that particular closure into code that reproduces it, the array of > constructor arguments needs to be [{} 3]. (I'm not sure what the map > argument is used for, but it seems to work when left empty, though not > when omitted entirely.
I did some more experimenting and the map attaches as metadata to the closure: user=> (def q (.newInstance (first (.getConstructors (.getClass (fn-maker3 2 1)))) (into-array Object [{:foo 1} 3 4]))) #'user/q user=> (q 10) 43 user=> (meta q) {:foo 1} There is also a second constructor for a closure that doesn't take a map. But it comes second in the sequence returned by .getConstructors. So you can use (second (.getConstructors ...)) with just the closures. Note that the fn-maker3 above was defined with: (defn fn-maker3 [x y] (fn [z] (+ (* z x) y))) and user=> ((fn-maker3 3 4) 10) 34 so it looks like the order of the constructor arguments can be rearranged from what you might expect given how the closure was defined. That wouldn't stop a clever compiler extension knowing the order needed (as it decided that order in the first place), saving them into the closure somehow (e.g. as metadata: {:recreate-args [4 3]}), and converting a closure into the code to recreate it (e.g. `(.newInstance (first (.getConstructors (class-for-name ~(.getName (.getClass closure))))) (into-array Object (quote ~(cons (meta closure) (:recreate-args (meta closure)))))) seems like it would evaluate to the required code, given the :recreate-args metadata, and it would preserve the metadata too). And since a non-closure also has two constructors -- besides the no-argument one, one accepting just a metadata map -- the above should in fact work to externalize any function object for reconstruction later (in any running session that has the function's class available) as long as the closed-over values (and the metadata) don't contain anything non-externalizable. In fact, if closure constructors only assoced the :recreate-args key into the closure's metadata automatically as an additional final step you could wrap the above in #=(eval ...) and use it to define print-dup for AFn. -- 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