Re: type hinting overloaded methods

2013-12-12 Thread Phillip Lord
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.


Re: type hinting overloaded methods

2013-12-11 Thread Mikera
You can't really avoid the instance checks: the underlying mechanic is that 
the JVM needs to figure out somehow at runtime which overloaded method 
version to call, since all it knows at compile time is that it has an 
arbitrary Object. 

instance? is the simplest way to do this. There are some fancier ways (e.g. 
using reflection or invokedynamic) but your case doesn't have very complex 
dispatch requirements so instance? checks are almost certainly the best 
option.

The good news is that instance? checks are extremely fast on the JVM so 
performance will still be great (certainly far better than if you used any 
kind of reflection)


On Tuesday, 10 December 2013 10:25:48 UTC, Phillip Lord wrote:



 I want to type hint an overloaded Java method. I used to have a function 
 like so 

 (defn iri [name] 
  (IRI/create name)) 

 Where IRI.create is one of 

 IRI.create(String) 
 IRI.create(URL) 
 IRI.create(File) 

 Type hinting the return value of this is straight-forward, but the 
 parameter is one of three types. The only way I seem to be able to get 
 this to work is to do lots of instance? checks... 


 (defn ^IRI iri 
   [name] 
   (cond 
(instance? String name) 
(IRI/create ^String name) 
(instance? java.net.URL name) 
(IRI/create ^java.net.URL name) 
(instance? java.io.File name) 
(IRI/create ^java.io.File name))) 

 which is a lot longer and, well, just not very nice. I could make this 
 neater with a macro -- something like... 

 (with-types [String, URL, File] 
(IRI/create name)) 

 which would expand into the cond form above. But the instance? checks 
 seem not ideal. Is there a better solution? 

 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.


Re: type hinting overloaded methods

2013-12-11 Thread Philipp Meier
Hi,

Am Mittwoch, 11. Dezember 2013 14:27:01 UTC+1 schrieb Mikera:

 You can't really avoid the instance checks: the underlying mechanic is 
 that the JVM needs to figure out somehow at runtime which overloaded method 
 version to call, since all it knows at compile time is that it has an 
 arbitrary Object. 

 instance? is the simplest way to do this. There are some fancier ways 
 (e.g. using reflection or invokedynamic) but your case doesn't have very 
 complex dispatch requirements so instance? checks are almost certainly the 
 best option.

 The good news is that instance? checks are extremely fast on the JVM so 
 performance will still be great (certainly far better than if you used any 
 kind of reflection)


Implementing a clojure protocol will give you fast dispatch on the first 
argument's type. 

-billy.

-- 
-- 
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.


Re: type hinting overloaded methods

2013-12-11 Thread Mikera
On Wednesday, 11 December 2013 13:37:24 UTC, Philipp Meier wrote:

 Hi,

 Am Mittwoch, 11. Dezember 2013 14:27:01 UTC+1 schrieb Mikera:

 You can't really avoid the instance checks: the underlying mechanic is 
 that the JVM needs to figure out somehow at runtime which overloaded method 
 version to call, since all it knows at compile time is that it has an 
 arbitrary Object. 

 instance? is the simplest way to do this. There are some fancier ways 
 (e.g. using reflection or invokedynamic) but your case doesn't have very 
 complex dispatch requirements so instance? checks are almost certainly the 
 best option.

 The good news is that instance? checks are extremely fast on the JVM so 
 performance will still be great (certainly far better than if you used any 
 kind of reflection)


 Implementing a clojure protocol will give you fast dispatch on the first 
 argument's type. 


Very true... it's a tradeoff:
- protocols allow open extension (which doesn't appear to be needed here?)
- instance? checks are even faster (although protocol dispatch is still 
pretty fast)
- protocols have some other quirks (e.g. not allowing primitive arguments)

In the case we have here (a small fixed number of types, no open dispatch 
required) I think I would prefer instance? checks (especially given a nice 
macro to remove the boilerplate). 

-- 
-- 
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.


Re: type hinting overloaded methods

2013-12-11 Thread Phillip Lord
Mikera mike.r.anderson...@gmail.com writes:

 On Wednesday, 11 December 2013 13:37:24 UTC, Philipp Meier wrote:
 Implementing a clojure protocol will give you fast dispatch on the first 
 argument's type. 


 Very true... it's a tradeoff:
 - protocols allow open extension (which doesn't appear to be needed here?)
 - instance? checks are even faster (although protocol dispatch is still 
 pretty fast)
 - protocols have some other quirks (e.g. not allowing primitive arguments)

 In the case we have here (a small fixed number of types, no open dispatch 
 required) I think I would prefer instance? checks (especially given a nice 
 macro to remove the boilerplate). 


Yeah, unfortunately I do need dispatch on primitive arguments, so
protocols fail for me.

I've been trying to get this to work as a macro, but am having problems
with this. The instance? check is easy to do, but adding the type hint
is much harder; I think that the ^macro expands at read time, so before
the macro expands, so it's not possible to construct the type hint.

I've tried to rewrite this with `with-meta' but can't get this to work
either since I think the meta is being added to the value.

My hope was to get something like this...

(defn ^IRI iri 
  [name]
  (with-type-hint
 [name [String java.net.URL java.io.File]]
 (IRI/create name)))

Am I really the first person to get this problem?

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.


Re: type hinting overloaded methods

2013-12-11 Thread Mikera
On Wednesday, 11 December 2013 14:50:36 UTC, Phillip Lord wrote:

 Mikera mike.r.an...@gmail.com javascript: writes: 

  On Wednesday, 11 December 2013 13:37:24 UTC, Philipp Meier wrote: 
  Implementing a clojure protocol will give you fast dispatch on the 
 first 
  argument's type. 
  
  
  Very true... it's a tradeoff: 
  - protocols allow open extension (which doesn't appear to be needed 
 here?) 
  - instance? checks are even faster (although protocol dispatch is still 
  pretty fast) 
  - protocols have some other quirks (e.g. not allowing primitive 
 arguments) 
  
  In the case we have here (a small fixed number of types, no open 
 dispatch 
  required) I think I would prefer instance? checks (especially given a 
 nice 
  macro to remove the boilerplate). 


 Yeah, unfortunately I do need dispatch on primitive arguments, so 
 protocols fail for me. 

 I've been trying to get this to work as a macro, but am having problems 
 with this. The instance? check is easy to do, but adding the type hint 
 is much harder; I think that the ^macro expands at read time, so before 
 the macro expands, so it's not possible to construct the type hint. 

 I've tried to rewrite this with `with-meta' but can't get this to work 
 either since I think the meta is being added to the value. 

 My hope was to get something like this... 

 (defn ^IRI iri 
   [name] 
   (with-type-hint 
  [name [String java.net.URL java.io.File]] 
  (IRI/create name))) 

 Am I really the first person to get this problem? 

 Phil 


Macros that generate type hints can get pretty ugly. 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)))


 

-- 
-- 
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.


Re: type hinting overloaded methods

2013-12-11 Thread Phillip Lord
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!

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.


type hinting overloaded methods

2013-12-10 Thread Phillip Lord


I want to type hint an overloaded Java method. I used to have a function
like so

(defn iri [name]
 (IRI/create name))

Where IRI.create is one of 

IRI.create(String)
IRI.create(URL)
IRI.create(File)

Type hinting the return value of this is straight-forward, but the
parameter is one of three types. The only way I seem to be able to get
this to work is to do lots of instance? checks...


(defn ^IRI iri
  [name]
  (cond
   (instance? String name)
   (IRI/create ^String name)
   (instance? java.net.URL name)
   (IRI/create ^java.net.URL name)
   (instance? java.io.File name)
   (IRI/create ^java.io.File name)))

which is a lot longer and, well, just not very nice. I could make this
neater with a macro -- something like...

(with-types [String, URL, File]
   (IRI/create name))

which would expand into the cond form above. But the instance? checks
seem not ideal. Is there a better solution?

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.


Re: type hinting overloaded methods

2013-12-10 Thread John D. Hume
On Tue, Dec 10, 2013 at 4:25 AM, Phillip Lord
phillip.l...@newcastle.ac.ukwrote:

 (defn ^IRI iri
   [name]
   (cond
(instance? String name)
(IRI/create ^String name)
(instance? java.net.URL name)
(IRI/create ^java.net.URL name)
(instance? java.io.File name)
(IRI/create ^java.io.File name)))

 which is a lot longer and, well, just not very nice. I could make this
 neater with a macro -- something like...

 (with-types [String, URL, File]
(IRI/create name))

 which would expand into the cond form above. But the instance? checks
 seem not ideal. Is there a better solution?


You could create and extend an IIriCreate protocol to String, URL, and
File.

I'd like to point out that Java doesn't provide a clean way to handle this
either.

-- 
-- 
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.