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

Reply via email to