Re: Clojure CLR and System.Double Behavior

2012-12-01 Thread Frank Failla
Thank you!

On Nov 30, 2012, at 11:35 PM, dmiller  wrote:

> Patched in master branch.
> 
> Clojure 1.5.0-master-SNAPSHOT
> user=>
> user=> (defn bar [^Double d] d)
> #'user/bar
> user=> (defn baz [^System.Double d] d)
> #'user/baz
> user=> (bar 1.2)
> 1.2
> user=> (baz 1.2)
> 1.2
> user=> (defprotocol FP (foo [_]))
> FP
> user=> (extend-protocol FP System.Double (foo [d] d))
> nil
> user=> (foo 1.2)
> 1.2
> 
> You can now type hint with double, Double and System.Double.
> 
> One should keep in mind that this is the CLR, not C# (or the JVM).  Thus, 
> int, Int32, System.Int32 and float, Single, System.Single.
> 
> Note  that a type hint such as ^System.Int32 x  is actually using the symbol 
> System.Int32 as the value for :tag -- that is how the LispReader works. 
> However, if you were to put :tag metadata on programmatically and actually 
> use the type System.Int32 -- well, that should work also. 
> 
> 
> -David
> 
>> 
>> On Thursday, November 29, 2012 11:02:19 AM UTC-6, ffailla wrote:
>>> 
>>> I have discovered some odd behavior when type-hinting fns with 
>>> ^System.Double:
>>> 
>>> user=> (defn bar [^System.Double d] d)
>>> #'user/bar
>>> user=> (bar 1.2)
>>> 2.35293190771409E-316
>>> user=> (bar 1)
>>> 2.35069794048985E-316
>>> 
>>> The same behavior occurs when extending double via extend-protocol or 
>>> extend-type:
>>> 
>>> user=> (defprotocol FooProto (foo [_]))
>>> user=> (extend-protocol FooProto System.Double (foo [d] d))
>>> nil
>>> user=> (foo 1.2)
>>> 2.25126584588049E-316
>>> 
>>> Any ideas?  Thanks.
>>> 
>>> -Frank Failla
> -- 
> 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

Re: Clojure CLR and System.Double Behavior

2012-11-30 Thread dmiller
Patched in master branch.

Clojure 1.5.0-master-SNAPSHOT
user=>
user=> (defn bar [^Double d] d)
#'user/bar
user=> (defn baz [^System.Double d] d)
#'user/baz
user=> (bar 1.2)
1.2
user=> (baz 1.2)
1.2
user=> (defprotocol FP (foo [_]))
FP
user=> (extend-protocol FP System.Double (foo [d] d))
nil
user=> (foo 1.2)
1.2


You can now type hint with double, Double and System.Double.

One should keep in mind that this is the CLR, not C# (or the JVM).  Thus, 
int, Int32, System.Int32 and float, Single, System.Single.

Note  that a type hint such as ^System.Int32 x  is actually using the 
symbol System.Int32 as the value for :tag -- that is how the LispReader 
works. However, if you were to put :tag metadata on programmatically and 
actually use the type System.Int32 -- well, that should work also. 


-David


> On Thursday, November 29, 2012 11:02:19 AM UTC-6, ffailla wrote:
>>
>> I have discovered some odd behavior when type-hinting fns with 
>> ^System.Double:
>>
>> user=> (defn bar [^System.Double d] d)
>> #'user/bar
>> user=> (bar 1.2)
>> 2.35293190771409E-316
>> user=> (bar 1)
>> 2.35069794048985E-316
>>
>> The same behavior occurs when extending double via extend-protocol or 
>> extend-type:
>>
>> user=> (defprotocol FooProto (foo [_]))
>> user=> (extend-protocol FooProto System.Double (foo [d] d))
>> nil
>> user=> (foo 1.2)
>> 2.25126584588049E-316
>>
>> Any ideas?  Thanks.
>>
>> -Frank Failla
>>
>>

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

Re: Clojure CLR and System.Double Behavior

2012-11-29 Thread dmiller
user=> (defn f [^Double x] x)
#'user/f
user=> (defn g [^double x] x)
#'user/g
user=> (f 1.0)
2.15078317008181E-316# GASP!
user=> (g 1.0)
1.0# CROWD APPLAUDS!

As you can see, there is a workaround: use ^double, not ^Double.  This 
matches what you would do in ClojureJVM.  Not to say the observed behavior 
isn't faulty and needs fixing.

This workaround is not possible for your extend-protocol example.  However, 
making System.Double work as you expect for primitive type hinting on fn 
arguments should also fix the extend-protocol problem.

Probably over this weekend.


 If you care to understand more fully: 

The problem stems from the difference in how primitives are handled in the 
JVM vs the CLR.  Sparing the details, it surfaces here in the fact that 
java.lang.Double and System.Double are significantly different.   
java.lang.Double is a (primitive) wrapper type,.  There is no equivalent in 
CLR; certainly a double can be boxed, but that is not the same.   
Said another way:  

In Java  void f(double x) { ... } is not the same as void f (Double x) { 
... }.  
In C#, void f(double x) {...} is the same as void f (Double x) { ... }.

Said yet another way
In JAVA: double.class != Double.class
in C#: typeof(double) == typeof(Double)

The distinction in the JVM is the reason ClojureJVM asks you to use the 
symbols double, float, int, etc. for type-hinting primitives.

At the moment, ClojureCLR matches the spec of ClojureJVM for type-hinting 
primitives.  if you hint with a type, such as System.Double or 
System.String, other things happen.  These other things match ClojureJVM 
mostly -- the problem being when the type is a primitive type such as 
System.Double.  

I think the only place there is a problem is primitive type hints on 
parameters and fn return types. Type hints used to avoid reflection are not 
a problem. 

Your protocol example has the same root problem.  Unfortunately, there is 
no simple workaround as with parameter type hints.  ClojureJVM has no 
equivalent to

(extend-protocol FooProto System.Double (foo [d] d))

because System.Double is not the same critter as java.lang.Double.  One can 
do

(extend-protocol FooProto java.lang.Double ... )

in ClojureJVM, but 

(extend-protocol FooProto double (foo [d] d))

is not possible.  


The problem is actually the same under the surface:

(extend-protocol FooProto T (foo [d] d))

 expands into something including  (foo [^T d) d) and we are back to our 
primitive type-hinting problem.  So, making primitive type-hinting work 
using System.Double should also solve this problem.

I'll work on it.  Should be this weekend.

-David






On Thursday, November 29, 2012 11:02:19 AM UTC-6, ffailla wrote:
>
> I have discovered some odd behavior when type-hinting fns with 
> ^System.Double:
>
> user=> (defn bar [^System.Double d] d)
> #'user/bar
> user=> (bar 1.2)
> 2.35293190771409E-316
> user=> (bar 1)
> 2.35069794048985E-316
>
> The same behavior occurs when extending double via extend-protocol or 
> extend-type:
>
> user=> (defprotocol FooProto (foo [_]))
> user=> (extend-protocol FooProto System.Double (foo [d] d))
> nil
> user=> (foo 1.2)
> 2.25126584588049E-316
>
> Any ideas?  Thanks.
>
> -Frank Failla
>
>

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

Clojure CLR and System.Double Behavior

2012-11-29 Thread ffailla
I have discovered some odd behavior when type-hinting fns with 
^System.Double:

user=> (defn bar [^System.Double d] d)
#'user/bar
user=> (bar 1.2)
2.35293190771409E-316
user=> (bar 1)
2.35069794048985E-316

The same behavior occurs when extending double via extend-protocol or 
extend-type:

user=> (defprotocol FooProto (foo [_]))
user=> (extend-protocol FooProto System.Double (foo [d] d))
nil
user=> (foo 1.2)
2.25126584588049E-316

Any ideas?  Thanks.

-Frank Failla

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