Re: import as a macro; dynamic imports?

2010-01-02 Thread Rich Hickey
On Fri, Jan 1, 2010 at 2:58 PM, Stuart Sierra
the.stuart.sie...@gmail.com wrote:
 I should have brought this up before 1.1 was released, but I'm
 bothered by the change of clojure.core/import from a function to a
 macro.

 If I'm creating a namespace dynamically, I can't evaluate the name of
 the class I want to pass to import.  The only way is to use
 undocumented Java functions, like:

 (defn import-name
  Import a class named c (a String) into namespace n.
  [n c]
  (.importClass n (clojure.lang.RT/classForName c)))

 Of course, I can write a macro that evaluates the strings, but that's
 not really what I want.  I want the equivalent of clojure.core/intern
 for classes.  Is there a better way?


Your example highlights the problem addressed by making import a
macro. Basically, Class.forName can't be proxied, i.e. any indirection
(such as wrapping it in a helper function like you did) breaks the
magic hack inside Class.forName that finds the classloader of the
caller by walking a fixed distance on the stack. Thus, such proxied
imports don't play well with specialized modular classloading
architectures (like OSGi etc) that expect you to be calling
Class.forName for any dynamic use. In such cases, you will be seeing
what the classloader of the wrapping function can see, rather than
what the caller can see.

On the path towards fixing this, I've added a (currently undocumented)
special op - clojure.core/import*, which will emit bytecode for a call
to Class.forName at the point of call (plus all the other stuff needed
to bind in the current namespace). This will ensure correct resolution
in the classloader of the caller. import expands into calls to
import*. Note it is String-based. This too is critical.

user= (clojure.core/import* java.util.List)
java.util.List

user= List
java.util.List

Note that, as a special op, import* still is not a function. The
bottom line is no ordinary function or method can do this job.

If you want to use import* as a workaround, please consider it alpha
and subject to change.

Rich

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


import as a macro; dynamic imports?

2010-01-01 Thread Stuart Sierra
I should have brought this up before 1.1 was released, but I'm
bothered by the change of clojure.core/import from a function to a
macro.

If I'm creating a namespace dynamically, I can't evaluate the name of
the class I want to pass to import.  The only way is to use
undocumented Java functions, like:

(defn import-name
  Import a class named c (a String) into namespace n.
  [n c]
  (.importClass n (clojure.lang.RT/classForName c)))

Of course, I can write a macro that evaluates the strings, but that's
not really what I want.  I want the equivalent of clojure.core/intern
for classes.  Is there a better way?

-SS

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