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