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 <[email protected]> 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 [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en