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

Reply via email to