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. The compiler can always give closure objects
> metadata amounting to the correct [{} 3] or whatever needed to
> recreate the closure object by calling its class's constructor.

Actually, this would require the arguments to be known at compile
time. For (let [x 3] (fn [y] (+ x y))) this is possible, but for a
return value from

(defn adder-maker [n]
  (fn [y] (+ n y)))

it's not.

But what are we really doing here? There are just two situations where
the compiler is being called. One is on-the-fly eval at runtime, and
then the bytecode could just be built with code that works something
along these lines:

makeJavaClassWithNullPublicStaticFieldItUses();
TheNewClass.THE_PUBLIC_STATIC_FIELD = someValue;

Here "someValue" would be an actual reference to the existing object
in memory, and it will work with closures and any other object, even
things like io streams backed by open file handles.

The second is for AOT compilation of Clojure code. In that case, what
we should probably aim for is that a) anything for which print-dup has
a method and b) anything that implements Serializable can be
externalized. For print-dupables you just print-dup to a string and
generate a class whose static initializer puts that back in through
the reader: something like

static {
    someVar = RT.readString("(sorted-map [1 2 3 4])");
}

The proof of concept for Serializables is similar:

static {
    someVar = (new ObjectInputStream
        (new ByteArrayInputStream
        (new byte[] {0x1b, 0xff, 0x3a, 0xa7, ...}))).readObject();
}

where the contents of the byte array literal are generated using
ObjectOutputStream/ByteArrayOutputStream, natch.

Closures, including ones whose arguments can't be known until runtime,
can easily be slapped with "implements Serializable" if they haven't
been already. Indeed, an "extends Serializable" on IFn, on top of the
above compiler modification to externalize anything serializable,
would suffice to make it possible to eval (and even AOT-compile) code
containing any embedded function objects, save for closures that have
closed over non-serializable objects.

-- 
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