--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--
This is that weird bug/glitch/unsupported feature when an actual
function object (as opposed to a symbol referring to a local or a var
holding one) is eval'd. It seems that this works for non-closure fns
but fails when the fn closes over a value from its context. I assume
that eval of sexps with embedded function objects is not supported,
and that it works even for some function objects is more or less
accidental.
Embed the quoted function code, e.g. (mapper `(partial + ~x) ...)
rather than (mapper (partial + x) ...), or make a defn out of the
function and call it by name, e.g. (defn foo ...) ... (mapper foo
...).
Note that the former only works if x is something eval'able itself,
such as a number or a string or something similar, or a Clojure data
structure composed ultimately of same. If it is, or contains, some
other kind of Java object, you've got trouble again.
The problem with generic objects in eval is partially solvable:
1. If the sexp is constructed and then eval'd in the same session, a
constant reference to the object could simply be embedded in the
generated bytecode as a class constant of reference type.
2. If the code is being AOT compiled, and the object implements
Serializable, it could be serialized as some sort of resource, and the
AOT output could include a static initializer that loads that resource
and stores a reference in a class constant.
Currently, neither of the above is implemented. The case that would
remain if they were would be:
3. The code is being AOT compiled and the object does not implement
Serializable.
That case subdivides as follows:
3a. The object cannot even in principle usefully be preserved across
sessions or moved between JVMs, e.g. because it contains file handles
or other native resources (ex.: FileInputStream).
3b. The object can in principle be preserved, and fairly simply; case
2 above would Just Work(tm) if you just slapped "implements
Serializable" on the thing's class.
3c. The object can in principle be preserved, but not simply; e.g.
WeakReference, which hooks into the GC; you'd need to first preserve
the referent (if not null) and then a) load that and then b) construct
a WeakReference to it in the target JVM instance. ReferenceQueues add
more complication in that instance. 3c could reduce to 3b in the case
of a proper writeObject/readResolve method pair.
However, for Clojure to support case 3b requires some kind of heap
introspection capability (likely involving native code) that allows it
to directly copy the bytes of an object's in-memory representation.
That prevents making 3c work via the writeObject/readResolve method,
and would presumably not work in sandboxed JVMs. I doubt it's
particularly practical to attempt to support case 3, just 1 and 2.
It is quite common to write functions that return sexps to simplify
writing macros; macros can call other functions to build parts of
their output.
The OP may also have been debugging a macro and reduced his problem to
a simple, reproducible example using such a function to generate the
problem part of the macro output and eval to trigger it.
There are also cases where eval is needed at run-time, such as dynamic
on-the-fly runtime function creation. Some of the most sophisticated
optimizations involve exploiting patterns in the input not discovered
until runtime, or compiling on the fly a version of an algorithm
specialized to a particular input; e.g. if you're going to try to
factor a big number, you might have code actually generate and compile
code to search for a factor for *that specific* number and then
execute it, and it might run faster than if that number were an
in-theory variable in the code, especially if the algorithm can be
changed depending on properties of the number.