Re: Clojure CLR and System.Double Behavior
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
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
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
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