Q1 This macro captures the correct namespace: (defmacro new* [type-name-as-symbol & args] `(clojure.lang.Reflector/invokeConstructor (ns-resolve ~*ns* ~type-name-as-symbol) (to-array '~args)))
Q2 Backquote ` is unnecessary for symbols, use standard quote ' Q3 Answer to 1 fixes this Q4 I'm not entirely sure, but roughly: . means namespace (or class!) / means field in namespace (or class!) That is why you have to use . for records, since records generate classes. Q5 I guess? Jonathan On Mon, May 9, 2011 at 2: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 -- 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