-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NaN can be used as a key in Map #6301
Conversation
Why do we want this? For me |
As noted in the issue description #5833, we want to comply with JavaScript's same-value-zero equality. The reason for that is because we want every value in Enso, including polyglot values, to have some hash code, and thus be used as a key in the map. |
This reverts commit 32d81f4.
# Conflicts: # distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso
This is not according to the JS spec.
Map.singleton (Map.singleton Number.nan 1) 42 . keys . at 0 . get Number.nan . should_equal 1 | ||
Map.singleton (Map.singleton Number.nan 1) 42 . at (Map.singleton Number.nan 1) . should_equal 42 | ||
|
||
Test.specify "should support atoms with custom comparators that violate reflexivity as keys" <| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test was copied from the issue description
Atom other, | ||
@Cached EqualsAtomNode equalsNode, | ||
@Cached IsSameObjectNode isSameObjectNode) { | ||
return isSameObjectNode.execute(self, other) || equalsNode.execute(self, other); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the fix for #6065, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -23,6 +25,15 @@ public static IsSameObjectNode build() { | |||
|
|||
public abstract boolean execute(@AcceptsError Object left, @AcceptsError Object right); | |||
|
|||
@Specialization | |||
boolean isSameDouble(double left, double right) { | |||
if (Double.isNaN(left) && Double.isNaN(right)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the handling of NaN
as being "same".
|
||
Test.specify "type_of Nothing is Nothing" <| | ||
Meta.type_of Nothing . should_equal Nothing | ||
|
||
Test.specify "NaN and NaN should be the same object" <| | ||
Meta.is_same_object Number.nan Number.nan . should_be_true | ||
(Number.nan == Number.nan) . should_be_false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nan != nan
, but Meta.is_same_object
gives true
. OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want/need any tests for polyglot handling of NaNs?
...untime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsSameObjectNode.java
Show resolved
Hide resolved
engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java
Outdated
Show resolved
Hide resolved
engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java
Outdated
Show resolved
Hide resolved
Test.specify "should be able to handle distinct on different primitive values" <| | ||
alter [1, "a"] . distinct . should_equal [1, "a"] | ||
alter ["a", 1] . distinct . should_equal ["a", 1] | ||
alter [Nothing, Nothing] . distinct . should_equal [Nothing] | ||
alter [Number.nan, Number.nan] . distinct . to_text . should_equal "[NaN]" | ||
alter [Nothing, Number.nan, Nothing, Number.nan] . distinct . to_text . should_equal "[Nothing, NaN]" | ||
alter [1, Nothing] . distinct . should_equal [1, Nothing] | ||
alter [Nothing, 1, Nothing] . distinct . should_equal [Nothing, 1] | ||
alter [1, Number.nan] . distinct . to_text . should_equal "[1, NaN]" | ||
alter [Number.nan, 1, Number.nan] . distinct . to_text . should_equal "[NaN, 1]" | ||
alter [1, Number.nan, 1] . distinct . to_text . should_equal "[1, NaN]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does distinct
work with other non-reflexive values, like My_Nan
? Can we get a test for it too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 6bae728
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, I'd just appreciate a test for My_Nan
in distinct
.
This also should at some point work consistently in Table.aggregate
- Aggregate_Column.Group_By
. I guess no need to add these tests now, but maybe we should add a note to #6292 to not forget about it? It is quite a brittle feature and easy to get wrong so it will be good to have tests for this case once available.
Fixes #5833 #6065
Pull Request Description
Number.nan
can be used as a key inMap
. This PR basically implements the support for JavaScript's Same Value Zero Equality so thatNumber.nan
can be used as a key inMap
.Important Notes
Meta.is_same_object Number.nan Number.nan
, andNumber.nan != Number.nan
- inspired by JS spec.Meta.is_same_object x y
impliesAny.== x y
, except forNumber.nan
.Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
./run ide build
.