For Lists equality there is comparison between their types:
Int[1,2,3] != Int?[1,2,3] != Obj[1,2,3]
I know it was documented, but who are users of that? Who needs to compare list types after content equality? Are there uses more common than plain content comparison?
Another gotcha here:
1.0 != 1.00
Since Decimal is a default floating-point type, I think, equals should be more intuitive, shouldn't it? Scale-aware comparisons may be implemented as a special method, again, if there's somebody who'll ever need them.
What do you think?
DanielFathThu 9 Dec 2010
About second example. That's not Fantom's fault though. They simply reuse .Net and Java classes which have that sort of implementation. Another thing to have in mind is security. sys::Decimal is made for security. If you don't need it then use sys::Float
As for the first I'm bit confused that Int[1,2,3] != Int?[1,2,3]. It not being null shouldn't affect overall type. Maybe make a new method that checks if it is the same type regardless of null-ability. As for Obj[1,2,3] != Int[1,2,3] that shouldn't surprise you since just by stating it is a regular object your list will be completely different.
If you wonder why 1.00 is Decimal and not float see discussion here:
> Why are decimal considered default? When I type 1.0 I expect it to be Float. So why does it default to Decimal instead? I mean I'm more likely to use Float than Decimal since Decimal is missing a lot of API and has a much lower use case than Float.
I think in normal usage, Decimal is what you want. If its simply an issue of APIs I'm sure we can add to Decimal - were there things you were looking for in particular?
tonskyThu 9 Dec 2010
I understand what decimals are for, but I didn’t get your example, even for financial applications 0.0is equal by all means to 0.00. Guys writing financial applications will be very surprised by the fact that 1.0 - 1.00 != 0.0. Sad if both .net and java have such a poor implementation.
For lists, I didn't see an use case for comparing lists’ types. If you see, please tell me. Lists are not important by themselves, their content does. It’s like saying that ArrayList(1,2,3) != LinkedList(1,2,3). Yes, they are working differently, but it’s content what’s important in almost all cases.
vkuzkokovThu 9 Dec 2010
Int[] and Int?[] are different functionally:
Int?[] x := ...
Int[] y := ...
z := null
x.add(z) // OK
y.add(z) // NullErr
By no means the same.
The fact that y can be casted to Int?[] is sometimes annoying but it's a trade-off for having simple generic types.
DanielFathThu 9 Dec 2010
even for financial applications 0.0 is equal by all means to 0.00. Guys writing financial applications will be very surprised by the fact that 1.0 - 1.00 != 0.0. Sad if both .net and java have such a poor implementation.
Nope. Those two aren't the same. And neither are 0.0f and 0.0.
Decimal aren't unintuitive either. If you want to compare them properly use compare or its shortcuts. See sys::Decimal.compare and sys::Decimal.equals. Probably reason equals isn't compare==0 is that it must use same fields for comparison as hash.
@vkuzokov: ArrayList and LinkedList have different functionality yet you can still compare them by their structure and not their function. I'm assuming that type comparison is done to optimize list comparison.
vkuzkokovThu 9 Dec 2010
ArrayList and LinkedList have different functionality.
From prospective of List interface they are the same. Int[] and Obj[] on the other hand have different behavior in Fantom runtime.
rfeldmanThu 9 Dec 2010
Not to belabor the point, but I don't think adding 0.1 to 0.0 three times and ending up with 0.300000000000000004 is "intuitive" by most standards. :) Mathematically it's plainly wrong as written; you need a solid understanding of how floats are represented under the hood to know why this happens, and I don't think very many developers do. After all, it doesn't come up that often.
That said, I also doubt it's worth doing a separate implementation from how Java and .net do this, especially due to interop concerns, so it's probably not terribly relevant how intuitive it may or may not be.
cheeserThu 9 Dec 2010
welcome it IEEE floating point specs. It sucks but it's how computers/memory works and is sufficient for most cases with the glaring exception of currency.
@vkuzkokov: I understand that they have different behavior. But they share the same structure and interface. Can't their behavior be synchronized (I'm assuming that you mean that Int?[] and Int[] aren't backed by same structure when implemented on a VM)?
jodastephenThu 9 Dec 2010
Given the confusion that can happen if equals is not compatible with compare, I've always strived to make them the same. However another approach is to say that if a class implements Comparable then compare() is used for == instead of equals(). Of course this approach doesn't work in Fantom as all classes have a compare() method and there is no Comparable interface to allow the rule to work. Which is a pity.
heliumFri 10 Dec 2010
In C# 1.0m == 1.00m is true, despite being represented differently internally.
tonskyFri 10 Dec 2010
@vkuzkokov Int[1,2,3].rw and Int[1,2,3].ro have different behaviour too, but are considered equal. That’s because when comparing lists, we are comparing content, not behaviour. Note that still nobody has a type comparison use case. It’s going to be like
And here are some notes from decimal.py source code:
# Decimal integers must hash the same as the ints
#
# The hash of a nonspecial noninteger Decimal must depend only
# on the value of that Decimal, and not on its representation.
# For example: hash(Decimal('100E-1')) == hash(Decimal('10')).
...
# The value of a nonzero nonspecial Decimal instance is
# faithfully represented by the triple consisting of its sign,
# its adjusted exponent, and its coefficient with trailing
# zeros removed.
It would be much more usable if Fantom’s Decimal will adjust its hash and equals functions to correspond to this rules.
tonsky Thu 9 Dec 2010
For
List
s equality there is comparison between their types:I know it was documented, but who are users of that? Who needs to compare list types after content equality? Are there uses more common than plain content comparison?
Another gotcha here:
Since
Decimal
is a default floating-point type, I think,equals
should be more intuitive, shouldn't it? Scale-aware comparisons may be implemented as a special method, again, if there's somebody who'll ever need them.What do you think?
DanielFath Thu 9 Dec 2010
About second example. That's not Fantom's fault though. They simply reuse .Net and Java classes which have that sort of implementation. Another thing to have in mind is security.
sys::Decimal
is made for security. If you don't need it then usesys::Float
Decimal is used in business system where there is a great chance someone could penny shave bank by saying.
As for the first I'm bit confused that
Int[1,2,3] != Int?[1,2,3]
. It not being null shouldn't affect overall type. Maybe make a new method that checks if it is the same type regardless of null-ability. As forObj[1,2,3] != Int[1,2,3]
that shouldn't surprise you since just by stating it is a regular object your list will be completely different.If you wonder why 1.00 is
Decimal
and not float see discussion here:tonsky Thu 9 Dec 2010
I understand what decimals are for, but I didn’t get your example, even for financial applications
0.0
is equal by all means to0.00
. Guys writing financial applications will be very surprised by the fact that1.0 - 1.00 != 0.0
. Sad if both .net and java have such a poor implementation.For lists, I didn't see an use case for comparing lists’ types. If you see, please tell me. Lists are not important by themselves, their content does. It’s like saying that
ArrayList(1,2,3) != LinkedList(1,2,3)
. Yes, they are working differently, but it’s content what’s important in almost all cases.vkuzkokov Thu 9 Dec 2010
Int[]
andInt?[]
are different functionally:By no means the same.
The fact that
y
can be casted toInt?[]
is sometimes annoying but it's a trade-off for having simple generic types.DanielFath Thu 9 Dec 2010
Nope. Those two aren't the same. And neither are 0.0f and 0.0.
Decimal
aren't unintuitive either. If you want to compare them properly use compare or its shortcuts. Seesys::Decimal.compare
andsys::Decimal.equals
. Probably reason equals isn't compare==0 is that it must use same fields for comparison as hash.@vkuzokov: ArrayList and LinkedList have different functionality yet you can still compare them by their structure and not their function. I'm assuming that type comparison is done to optimize list comparison.
vkuzkokov Thu 9 Dec 2010
From prospective of
List
interface they are the same.Int[]
andObj[]
on the other hand have different behavior in Fantom runtime.rfeldman Thu 9 Dec 2010
Not to belabor the point, but I don't think adding 0.1 to 0.0 three times and ending up with 0.300000000000000004 is "intuitive" by most standards. :) Mathematically it's plainly wrong as written; you need a solid understanding of how floats are represented under the hood to know why this happens, and I don't think very many developers do. After all, it doesn't come up that often.
That said, I also doubt it's worth doing a separate implementation from how Java and .net do this, especially due to interop concerns, so it's probably not terribly relevant how intuitive it may or may not be.
cheeser Thu 9 Dec 2010
welcome it IEEE floating point specs. It sucks but it's how computers/memory works and is sufficient for most cases with the glaring exception of currency.
DanielFath Thu 9 Dec 2010
@rfeldman: Not to mention this gem:
@vkuzkokov: I understand that they have different behavior. But they share the same structure and interface. Can't their behavior be synchronized (I'm assuming that you mean that
Int?[]
andInt[]
aren't backed by same structure when implemented on a VM)?jodastephen Thu 9 Dec 2010
Given the confusion that can happen if equals is not compatible with compare, I've always strived to make them the same. However another approach is to say that if a class implements Comparable then compare() is used for == instead of equals(). Of course this approach doesn't work in Fantom as all classes have a compare() method and there is no Comparable interface to allow the rule to work. Which is a pity.
helium Fri 10 Dec 2010
In C# 1.0m == 1.00m is true, despite being represented differently internally.
tonsky Fri 10 Dec 2010
@vkuzkokov
Int[1,2,3].rw
andInt[1,2,3].ro
have different behaviour too, but are considered equal. That’s because when comparing lists, we are comparing content, not behaviour. Note that still nobody has a type comparison use case. It’s going to be likebut that doesn’t make sense.
@helium Same for python's
decimal.Decimal
classAnd here are some notes from
decimal.py
source code:It would be much more usable if Fantom’s
Decimal
will adjust itshash
andequals
functions to correspond to this rules.