Have you considered factory functions and macros? Macros might suit better if you are dealing with various records.
(defmacro instance ([^Class c] `(new ~c)) ([^Class c & more] `(new ~c ~@more))) Since macros are expanded, qualified vs unqualified issue will be taken care of automatically - i.e. the place where you use the macro should have import'ed the class. Couple this with factory functions and you may not even need to import the classes. Maybe if you can share the use case you are trying to address, that would help understand it better. Regards, Shantanu On May 9, 5:00 pm, Simon Katz <nomisk...@gmail.com> wrote: > I'm trying to implement a function similar to new, but where > the type is not known at compile time -- so I want to evaluate > the first argument. > > With the help of Google, I found the approach used in new* > below: > > (ns dynamic-new) > > (defn new* [type-name-as-symbol & args] > (clojure.lang.Reflector/invokeConstructor > (resolve type-name-as-symbol) > (to-array args))) > > In simple situations it works ok: > > (ns my-namespace > (:refer dynamic-new)) > > (defrecord MyRecord [a b c]) > > (= (new MyRecord 1 2 3) > (new* 'MyRecord 1 2 3) > (new* 'my-namespace.MyRecord 1 2 3)) > => true > > (= (new java.util.Date 0 0 1) > (new* 'java.util.Date 0 0 1)) > => true > > But there's a problem with unqualified symbols. > Continuing with definitions in my-namespace... > > (defn instantiate-qualified [] > (new* 'my-namespace.MyRecord 1 2 3)) > > (defn instantiate-unqualified [] > (new* 'MyRecord 1 2 3)) > > (defn both-funs-same? [] > (= (instantiate-qualified) > (instantiate-unqualified))) > > (both-funs-same?) > => true > > OK -- no surprises above. > > But... > > (ns another-namespace) > (try (do (my-namespace/instantiate-unqualified) > "succeeded") > (catch Exception e "failed")) > => "failed" > > In another-namespace, the call of my-namespace/instantiate-unqualified > fails because there is no data type or class named MyRecord in that > namespace. > > And... > > (ns a-namespace-with-a-different-MyRecord) > (defrecord MyRecord [a b c]) ; two MyRecords in different > namespaces > (my-namespace/instantiate-unqualified) > => #:a-namespace-with-a-different-MyRecord.MyRecord{:a 1, :b 2, :c > 3} > > So, the function my-namespace/instantiate-unqualified has created > an instance of a-namespace-with-a-different-MyRecord.MyRecord. > This could be a source of confusing bugs. > > Now my questions: > > Q1. Is this basically the right approach, or is there some other > way to implement new*? > > Q2. I can use syntax-quote to qualify a symbol at read time: > (defn instantiate-unqualified [] > (new* `MyRecord 1 2 3)) > Is that the right way to go? > > Q3. It might be a good idea to check in new* that the symbol passed > to it is qualified. In combination with the use of syntax-quote, > this might be a good solution. Is there a way to check for this? > (Perhaps checking whether the symbol's name contains a "."? But > (a) that's slow and (b) I'm not sure it's good enough.) > > I had thought that I might be able to use the namespace function > to check this, because > (namespace 'my-namespace/foo) => "my-namespace" > but unfortunately > (namespace 'my-namespace.MyRecord) => nil > > Q4. Given that symbols containing "." are qualified, is > (namespace 'my-namespace.MyRecord) => nil > correct behaviour? > (I think I don't fully understand symbols containing "." but > not "/".) > > Q5. I've seen the phrase "fully-qualified symbol" used in a few > places. Does this simply mean "qualified symbol"? If there > is such a thing as a partially-qualified symbol, checking > that a symbol is qualified may not help. > > Simon -- 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