Before I start, please remember the finesse of numbers in groovy: 0.1 is a BigDecimal, if you want a Double, you have to write 0.1D.
Also, I might be seeing something completely wrong here, corrections are more than welcome!
So, what is the result of code below?
List
println lst[0].class
println lst[1].class
println 0.1 == lst[0]
println 0.1 == lst[1]
println 0.1 in [lst[0]]
println 0.1 in [lst[1]]
Well, in my book the interpreter should whine on the first line and stop. I am declaring a List of doubles and putting a BigDecimal in. But it doesn’t. I suppose this is either a bug or some type messing coming from a the not very clear way (for me) Groovy handles types: If I say the type of lst is a List of Doubles, I expect it to behave statically. Either that or the language is misguiding me is allowing me to specify the type and then ignoring it, not good.
So, the result:
class java.math.BigDecimal
class java.lang.Double
true
true
true
false
Note that 0.1 is equal to 0.1D (i.e. BigDecimal is equal to Double. For me it makes sense as they have the same value) BUT 0.1 is not in [0.1D]. This, I suppose can only be categorized as a bug (or as something completely unintuitive).
I understand that numbers are not an easy thing to address (precision vs efficiency), but this strikes me as nonintuitive in 2 fronts (type declaration and number/equality behavior)
Correct me if I am wrong (I can see myself doing a big blunder with equality operator semantics, but I have trouble accepting that groovy lets me put a BigDecimal inside a list of double)…











James Iry says:
In this comment I’m using square brackets instead of angle brackets to prevent them from being eaten.
This isn’t a problem related to different numeric types. Groovy is essentially a dynamically typed language. It has (almost) no static type system.
Even when you give type annotations like “List[Double]” you are specifying a runtime check, not a static check. And that runtime check is unfortunately very simple: it has to be a List, but Groovy doesn’t care what’s in the list. It’s not really Groovy’s fault. In Java, parametric types like List[Double] are erased at runtime to just List, so Groovy has inherited that limitation in its runtime type checking.
groovy:000> List[Double] lst = [1, "hello", new RuntimeException(), "I can be" + " whatever"]
===> [1, hello, java.lang.RuntimeException, I can be whatever]
For a statically typed alternative, check out Scala. Generally it’s a bit more succinct than Groovy except when you really need dynamic meta-programming.
scala> val lst = List(1.0, 2.0, 3.0)
January 5, 2009, 22:54lst: List[Double] = List(1.0, 2.0, 3.0)
tiago says:
James,
First, thanks for your insightful comments. I have to say I have started with Scala (and migrated to Groovy). I guess am a metaprogramming freak. A summary of my reasons can be found here. It would be fantastic to know that there are updates on the metaprogramming part.
I fully agree with our assessment of parametric types. Generics are the worse thing I can thing of in Java.
January 5, 2009, 23:14James Iry says:
So you don’t like Scala because its inference isn’t as complete as Caml, but you like to use explicit types in Groovy?
There have been some updates to dynamic metaprogramming in Scala via something called Manifests which are, in part, a way to reify generic type parameters. But any serious metaprogramming that Scala gets will likely be syntactic metaprogramming a’la template Haskell or Nemerle. Don’t expect the dynamic metaprogramming found in Ruby and Groovy.
Generics aren’t the worst thing in Java by a long shot. Not even erasure is (after all, Caml’s type system is implemented entirely with erasure).
January 6, 2009, 03:45Aaron Tuwhangai says:
The == operator coerces its arguments to the same type before comparing them, so “0.1 == 0.1D” is coerced to mean “0.1 == 0.1″.
The reason that “0.1 in [0.1D]” returns false is that “0.1.equals(0.1D)” also returns false. This correctly follows the Java rules for equals() rather than being a Groovy thing.
January 6, 2009, 05:54tiago says:
Aaron: Thanks for the comment. I guess I was lazy. Equal semantics was more or less obviously the source of the problem and I could have dig deeper myself.
James: I think we are entering the realm of the subjective here. I mean, for me, very personally, metaprogramming is a must have. For me generics are the worse of Java. Your mileage may vary and we might have a lot of interesting discussions around these, but, at the end, personal choices dictate what we find acceptable/desirable.
January 6, 2009, 16:11