Phillip Lord <phillip.l...@newcastle.ac.uk> writes:

> Mikera <mike.r.anderson...@gmail.com> writes:
>
>> On Wednesday, 11 December 2013 14:50:36 UTC, Phillip Lord wrote:
>> Macros that generate type hints can get pretty ugly. 
>
> Yes, I notice that!
>
>> I ran into the same problem with vectorz-clj
>>
>> The following pattern ended up working for me: the trick to to create a 
>> local symbol that you can tag
>>
>> (defmacro tag-symbol [tag form]
>>   (let [tagged-sym (vary-meta (gensym "res") assoc :tag tag)]
>>     `(let [~tagged-sym ~form] ~tagged-sym)))
>
>
> Will try, thanks for the pointer!


That is the strangest macro ever. It expands to something like

(let [x y] x)

yet still actually does something useful.

My end solution looks like this:

(defmacro with-types
  [spec & body]
  "Given a spec of the form [symbol [types]] evaluate body if
and only the value of symbol is an instance? of one of types. The symbol is
type-hinted to the type of the first of types to match.

The main aim for this is to avoid reflective calls to overloaded methods in
Java. So if we have an overloaded static method call:

C.met(String)
C.met(Double)
C.met(Boolean)

  (with-types [val [String Double Boolean]]
    (C/met val)

will call met without reflection, so long as val is one of String, Double or
Boolean. If none of the types are matched, an IllegalArgumentException will be
thrown."
  (let [hint-var# (first spec)
        types# (second spec)]
    (if (seq types#)
      (let [type# (first types#)]
        `(let [~hint-var#
               (tawny.util/tag-symbol ~type# ~hint-var#)]
           (if (instance? ~type# ~hint-var#)
             ~@body
             (with-types
               [~hint-var# ~(vec (rest types#))]
               ~@body))))
      `(throw (IllegalArgumentException. "No types have been matched")))))

Which works nicely and seems to compile down to code without reflection.

Thanks again!

Phil

-- 
-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to