views:

202

answers:

3

In Clojure, given a class name as a string, I need to create a new instance of the class. In other words, how would I implement new-instance-from-class-name in

(def my-class-name "org.myorg.pkg.Foo")
; calls constructor of org.myorg.pkg.Foo with arguments 1, 2 and 3
(new-instance-from-class-name  my-class-name 1 2 3) 

I am looking for a solution more elegant than

  • calling the Java newInstance method on a constructor from the class
  • using eval, load-string, ...

In practice, I will be using it on classes created using defrecord. So if there is any special syntax for that scenario, I would be quite interested.

+1  A: 

Since 'new' is a special form, I'm not sure there you can do this without a macro. Here is a way to do it using a macro:

user=> (defmacro str-new [s & args] `(new ~(symbol s) ~@args))
#'user/str-new
user=> (str-new "String" "LOL")
"LOL"

Check out Michal's comment on the limitations of this macro.

Rayne
Note that this will only work if the `s` received by the macro is a (literal) string and not an arbitrary expression evaluating to a string. In the latter case, there's no avoiding `eval` or reflective instance construction.
Michał Marczyk
Thanks for pointing that out. Didn't think to mention that.
Rayne
I am afraid that s will not be a literal string. I have edited the question to reflect this.
chris
+7  A: 
Chouser
Excellent! The second option is obviously a very general technique. I've already used it in another way.
chris
+1  A: 

Here is a technique for extending defrecord to automatically create well-named constructor functions to construct record instances (either new or based on an existing record).

http://david-mcneil.com/post/765563763/enhanced-clojure-records

Alex Miller