conditional gen-and-load-class

82 views
Skip to first unread message

Parth Malwankar

unread,
Aug 23, 2008, 11:32:09 AM8/23/08
to Clojure
Hello,

I have a file that has an exception defined:

(gen-and-load-class 'user.MyFailure :extends Exception)

; ... other stuff here ...

Based on the docs I understand "a class generated this way
can be loaded only once" which makes sense. However,
during development it is fairly common to do a "load-file"
multiple times in the REPL. This works fine for everything
however when we have "gen-and-load-class" this fails.

user=> (load-file "exception.clj")
user.MyFailure

; .... based on some interaction make
; .... changes to exception.clj

user=> (load-file "exception.clj")
java.lang.LinkageError: loader (instance of clojure/lang/
DynamicClassLoader): attempted duplicate class definition for name:
"user/MyFailure"
java.lang.LinkageError: loader (instance of clojure/lang/
DynamicClassLoader): attempted duplicate class definition for name:
"user/MyFailure"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at
clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:
39)
at clojure.gen_and_load_class__1856.doInvoke(genclass.clj:454)
at clojure.lang.RestFn.invoke(RestFn.java:443)
at user.eval__2537.invoke(exception.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:3847)
at clojure.lang.Compiler.load(Compiler.java:4136)
at clojure.lang.Compiler.loadFile(Compiler.java:4103)
at clojure.lang.RT$3.invoke(RT.java:285)
at user.eval__2534.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3847)
at clojure.lang.Repl.main(Repl.java:75)
user=>

Most of the time once the exceptions are defined the
would just sit there in the file while the user adds and
tweaks other functions based on the interaction at the
repl. The above failure requires us to restart the repl
to check any change.

Is there any way of allowing reload of a file with
gen-and-load-class? Maybe something like:

(when (not-loaded 'user.MyClass)
(gen-and-load-class 'user.MyFailure :extends Exception))

This will ease development and the user will need
to restart the repl only if the above class definition is
changed.

Thanks.
Parth

Parth Malwankar

unread,
Aug 23, 2008, 11:27:37 PM8/23/08
to Clojure
Never mind. This simple block seems to do the trick.

(when (not (resolve '*init-done*))
(gen-and-load-class 'user.MyFailure :extends Exception))
(def *init-done* true)

Not sure if there is a more elegant way to do it but this
seem to work fine.

> Thanks.
> Parth

Chouser

unread,
Aug 24, 2008, 12:05:49 AM8/24/08
to clo...@googlegroups.com
On Sat, Aug 23, 2008 at 11:27 PM, Parth Malwankar
<parth.m...@gmail.com> wrote:
>
> (when (not (resolve '*init-done*))
> (gen-and-load-class 'user.MyFailure :extends Exception))
> (def *init-done* true)
>
> Not sure if there is a more elegant way to do it but this
> seem to work fine.

You could simply catch the exception.

(try (gen-and-load-class 'user.MyFailure :extends Exception)
(catch LinkageError e))

That will succeed (and return the class) the first time, and fail
silently after that. Not sure if that counts as "more elegant" or
not. :-)

gen-interface handles this for you, and takes the extra step of
warning you if the new definition is different from the old
definition. There's no reason gen-class couldn't do the same thing,
it just doesn't yet.

--Chouser

Reply all
Reply to author
Forward
0 new messages