Unexpected equality behavior (java.lang.Long)
João Paulo Varandas
joaovarandas at inpaas.com
Tue Aug 16 14:16:42 UTC 2016
Hi Hannes.
Thanks for reviewing this. Seeing it from this perspective:
Longs are just like JS Number wrappers.
Made me believe the situation was not that bad too. Telling developers to
'unwrap' numbers using " x = Number(x); " would not be a bad idea.
With that in mind, any number comparison would have to be made unwrapping
data first ... But, we would also need to test nulls first, because:
While "null == 0" yields false, and obviusly "null === 0" yields false.
Number(null) === Number(0) would yield true.
Thus, we would need:
function unwrapNumber(x) {
return x == null ? null : Number(x);
}
And also, to tell developers to call unwrapNumber() everytime they need to
compare a Number ...
I don't know if you agree with me, but now I see this as an anti-pattern.
---
Anyway... It seems that all the fuzz is because of that "bug" with Long
numbers and double. And I'm sorry that I did not look further into that
issue.
Maybe we should look further into that, and try to make that any number
below Number.MAX_SAFE_INTEGER (9007199254740991), work the way is expected
inside JS evaluations ...
*João Paulo Varandas*+55 11 99889-2321
joaovarandas at inpaas.com
2016-08-16 6:23 GMT-03:00 Hannes Wallnöfer <hannes.wallnoefer at oracle.com>:
> After exploring various options I don’t think there’s anything we can do
> to go back and treat longs like numbers in Nashorn.
>
> The ECMA spec is quite clear that there are numbers and object, and
> comparison of the latter is by reference, not value. So having some kind of
> in-between states is not really an option. Making longs numbers again would
> be quite a small and harmless change within the language (without reverting
> to longs as internal data type). Precision would be lowered to doubles for
> large longs, but that wouldn’t be a problem for most users.
>
> However, the problems starts where longs as numbers inherit from
> Number.prototype. Of course, all methods in Number.prototype are specified
> for double values, and the toString methods collides with toString in
> java.lang.Long. Having a toString method that rounds large longs to the
> nearest double value is a no-go. Nor is extending all methods in
> Number.prototype to handle longs are viable options.
>
> There is one issue we need to fix to improve handling of longs and other
> instances of java.lang.Number though (thanks to Attila for first pointing
> this out): Currently, java.lang.Numbers not treated as numbers in the
> ToPrimitive operation with Number hint. This means less-than/greater-than
> operators will treat those number objects as strings instead of converting
> to double. I filed a bug for this, and will back port it to JDK 8u:
>
> https://bugs.openjdk.java.net/browse/JDK-8163945
>
> All things considered, there are some things that make me think the
> situation is not as bad as some seem to believe. For one, the new treatment
> of Longs (with the fix for the bug above) is consistent with how JavaScript
> Number objects/wrappers are treated. Comparing two Number wrappers for the
> same value will also evaluate to false with both == and === operators,
> while comparing them to the primitive number with == will evaluate to true.
>
> new Number(1) == new Number(1) // false
> new Number(1) === new Number(1) // false
> new Number(1) == 1 // true
> new Number(1) === 1 // false
>
> So Longs are just like JS Number wrappers. They are object wrappers for
> numeric values. If needed they can easily converted to primitive numbers by
> calling the global Number() function without „new“ keyword, eg:
>
> if (typeof x === „object“)
> x = Number(x);
>
> This is a common pattern in JavaScript even without Java longs, so I think
> it’s acceptable.
>
> Hannes
>
>
> > Am 05.08.2016 um 15:45 schrieb Hannes Wallnöfer <
> hannes.wallnoefer at oracle.com>:
> >
> > Hi Joao Paulo,
> >
> > thanks for the report.
> >
> > We do realize that this change caused problems for a lot of people, and
> we are sorry for that, and thinking how we can improve things.
> >
> > I still think we were right to remove longs as internal number
> representation. But maybe we went to far with this, and should allow people
> to deal with longs as numbers, assuming they are all right with an eventual
> loss of presentation.
> >
> > This needs some discussion and thinking and experimentation. I’ll get
> back to you after the weekend.
> >
> > Hannes
> >
> >
> >
> >> Am 05.08.2016 um 04:40 schrieb João Paulo Varandas <
> joaovarandas at inpaas.com>:
> >>
> >> By the way, I just found out some bugs filed about Long objects:
> >> https://bugs.openjdk.java.net/browse/JDK-8162771
> >> https://bugs.openjdk.java.net/browse/JDK-8161665
> >>
> >> And a twitter discussion:
> >> https://twitter.com/provegard/status/755010492112986112
> >>
> >> I'd like to bring this up again if we have more room for discussion ...
> >> --
> >>
> >> 2 Long values returned from a database and sent to a javascript
> evaluation code can't be compared the way it should in JavaScript... If I
> have some validation code, I don't know if the source is some JavaScript
> input (number), or the source is a database query
> (object/Long/Integer/Double).
> >>
> >> It's really hard to decide when sometimes x==y should be compared as
> x.equals(y) and sometimes not... and sometimes, at the same point in code I
> should do a lot of conditional operations, to resolve a simple
> comparison... and that comparison does not work if the data source is a
> Java object or a JavaScript object.
> >>
> >> The problem with the current solution is that comparison between
> different types would never work ...
> >>
> >> Seeing that
> >> jjs> new java.lang.Long(2147483648) == "2147483648"
> >> returns true
> >>
> >> But
> >> jjs> new java.lang.Long(2147483648) == new java.lang.Long(2147483648)
> >> returns false
> >>
> >> Is something really hard to accept ...
> >> And that "equals" approach will work ONLY if I compare Long to Long.
> And I see this as a regression when talking about evaluating JavaScript
> code.
> >>
> >>
> >>
> >> Sorry about the long post, but I would really appreciate if we could
> revalidate this and think about what the current situation represents from
> ecmascript's point of view.
> >>
> >>
> >>
> >>
> >>
> >> -08-04 22:43 GMT-03:00 João Paulo Varandas <joaovarandas at inpaas.com>:
> >> Sorry Tomas.
> >>
> >> Either you did not read the message(which would be indeed a beginner's
> mistake), or you are misleading the discussion.
> >>
> >> What you said, about equality and references would be true if we were
> talking about Java code. This is jdk8-nashorn's mailing list and I'm
> talking about JavaScript evaluation inside the JVM.
> >>
> >>
> >> Comparison operators inside the script engine follow JavaScript rules
> and not Java rules.
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >> João Paulo Varandas
> >> +55 11 99889-2321
> >> joaovarandas at inpaas.com
> >>
> >>
> >> 2016-08-04 20:08 GMT-03:00 Tomáš Zíma <tomas at tzima.cz>:
> >> A classical beginner's mistake. You are using Java objects and
> comparing references, not the values, so this is expected behavior. Simply
> compare the objects using equals().
> >>
> >>
> >> On 4.8.2016 15:48, João Paulo Varandas wrote:
> >> Hi guys!
> >>
> >> It seems that version 1.8.0_101 has a bug in equality for same java data
> >> types (java.lang.Long).
> >>
> >> Check that:
> >> jjs> new java.lang.Long(10) == new java.lang.Long(10)
> >> false
> >>
> >> Oops!?
> >>
> >> See the gist:
> >> https://gist.github.com/joaovarandas/51567bd3b576d48a4c574d60d5a60ba3
> >>
> >> The results for all types should be ...
> >> == true
> >> === true
> >> equals true
> >>
> >> But for java.lang.Long and java.math.BigDecimal:
> >> == false
> >> === false
> >> equals true
> >>
> >> Maybe we could expand the test to other classes too, but the issue ...
> >> - It does happen in 1.8.0_101.
> >> - It does not 1.8.0_91.
> >> - It does happen with other classes (BigDecimal).
> >> - It does not happen with String.
> >> - It does not happen with Integer.
> >>
> >>
> >> I understand this is not an expected behavior. For now I'm rolling back
> >> to 1.8.0_91 in my environments.
> >>
> >>
> >>
> >> Do you me to file a bug?
> >>
> >> Thanks
> >> J
> >>
> >>
> >>
> >>
> >>
> >>
> >> "Esta mensagem, incluindo seus anexos, pode conter informacoes
> confidenciais e privilegiadas.
> >> Se voce a recebeu por engano, solicitamos que a apague e avise o
> remetente imediatamente.
> >> Opinioes ou informacoes aqui contidas nao refletem necessariamente a
> posicao oficial da Plusoft."
> >>
> >> "Antes de imprimir, pense em sua responsabilidade e compromisso com o
> MEIO AMBIENTE"
> >
>
>
--
"Esta mensagem, incluindo seus anexos, pode conter informacoes
confidenciais e privilegiadas.
Se voce a recebeu por engano, solicitamos que a apague e avise o remetente
imediatamente.
Opinioes ou informacoes aqui contidas nao refletem necessariamente a
posicao oficial da Plusoft."
"Antes de imprimir, pense em sua responsabilidade e compromisso com o MEIO
AMBIENTE"
More information about the nashorn-dev
mailing list