Lazy load of imports

95 views
Skip to first unread message

BerlinBrown

unread,
Jun 11, 2009, 5:30:57 PM6/11/09
to Clojure
I have a Clojure applications with different files, different
namespaces and I have imports of classes within those files/
namespaces.

lets say

(import java.io File)
(import thepackage SomeClass)

Is it possible to lazy load the imports of the class. For example, if
I start my app, I will get an error if thepackage.SomeClass is
unavailable. Even though I haven't instantiated an Object of
SomeClass type.

Is it possible to dynamically set a referance to SomeClass and then do
the import. E.g.

1. Launch Clojure application

2. Do: Class.forName("thepackage.SomeClass")

...
...
3. and then do the lazy import of (import thepackage SomeClass)

Stephen C. Gilardi

unread,
Jun 11, 2009, 6:51:57 PM6/11/09
to clo...@googlegroups.com

On Jun 11, 2009, at 2:30 PM, BerlinBrown wrote:

> I have a Clojure applications with different files, different
> namespaces and I have imports of classes within those files/
> namespaces.

I don't think the following is exactly what you're asking for, but you
can use "clojure.contrib.core/new-by-name" to do something like what
you described.

Here's an example from clojure.contrib.miglayout.internal:

(def MigLayout "net.miginfocom.swing.MigLayout")

[...]

(.setLayout (new-by-name MigLayout layout column row))

[...]

Using this technique I was able to change clojure.contrib.miglayout's
dependence on the miglayout jar from compile time to runtime.

--Steve

Berlin Brown

unread,
Jun 11, 2009, 8:20:33 PM6/11/09
to Clojure
>  smime.p7s
> 3KViewDownload

Now, that is close, not entirely but close enough.

Do you think there will be any performance hits.

Stephen C. Gilardi

unread,
Jun 11, 2009, 8:48:06 PM6/11/09
to clo...@googlegroups.com
On Jun 11, 2009, at 5:20 PM, Berlin Brown wrote:

Now, that is close, not entirely but close enough.

Cool.

Do you think there will be any performance hits.

I haven't run any tools on it. In looking around the reflection-related code in clojure.lang, it looks to me like the performance of new-by-name should be similar to that of other Clojure code that uses reflection rather than direct calls.

--Steve

Chouser

unread,
Jun 12, 2009, 10:31:56 AM6/12/09
to clo...@googlegroups.com
On Thu, Jun 11, 2009 at 8:48 PM, Stephen C. Gilardi<sque...@mac.com> wrote:
>
> > Do you think there will be any performance hits.
>
> I haven't run any tools on it. In looking around the reflection-related code
> in clojure.lang, it looks to me like the performance of new-by-name should
> be similar to that of other Clojure code that uses reflection rather than
> direct calls.

I think that's correct. In my experience a call that
requires runtime reflection like this is on the order of 50
times slower than a method call that is made directly.
Depending on how often it gets called, I think that would
generally count as a "performance hit".

Another option you could consider: moving all code that
requires that class into a separate .clj file, then using
'load' when you need it. This would allow you to AOT
compile (or not) and suffer none of the runtime reflection
cost.

Yet another option would be to eval a constructor function.
Something like:

(defn make-foo [arg1 arg2]
(eval `(defn ~'make-foo [a1# a2#] (Foo. a1# a2#)))
(make-foo arg1 arg2))

Note that's not well tested. I'm not sure, but you may have
trouble elsewhere if you try to type-hint Foo. But
basically, that defines a make-foo such that the first time
it's called it compiles a new make-foo that will actually
create instances of Foo. This will be slow, but subsequent
calls to make-foo should run at full compiled speed.

Both those options may be pretty painful depending on what
you're actually doing, so if I were you I'd try new-by-name
first and only if you're sure it's too slow would I try
another option.

--Chouser

Berlin Brown

unread,
Jun 13, 2009, 8:06:58 AM6/13/09
to Clojure


On Jun 12, 10:31 am, Chouser <chou...@gmail.com> wrote:
If I do the dynamic call to "load", and in my clojure script I have a
namespace defined. Load will still work and I will be able to
reference that namespace later?
Reply all
Reply to author
Forward
0 new messages