`Object.is` semantics?
dead-claudia opened this issue ยท 15 comments
Edit: clarity.
Two questions on this subject:
- Should
Object.is
carry pointer equality semantics or===
semantics? - If it carries pointer equality semantics, how much of its identity should be left to the implementation (for optimization purposes)?
I'm leaning towards this:
- Pointer equality.
(a => Object.is(a, a))(o)
must returntrue
for every const valueo
,Object.is(a, b)
must returnfalse
ifa !== b
or ifa
andb
are both const values from different realms, and it's implementation-dependent in all other cases.
===
.
The fact that ===
uses different semantics from Object.is
is one of the worst parts of the language. We are not going to add any new values for which the two are not equivalent.
@bakkot Just to clarify, would we at least say things like Object.is(#{a: 0}, #{a: -0})
is false
while #{a:0} === #{a: -0}
is true?
@littledan I hadn't thought about #{a:0} === #{a: -0}
. I would lean towards that being false, partly because I think #{a:NaN} === #{a: NaN}
should be true.
Interesting. Could you explain why you have those two intuitions?
Mostly because there are currently exactly three values in the language for which ===
is not equality, and introducing an infinite set of new ones seems bad.
Interesting. Yeah, I can definitely picture a lot of code that checks for NaN this way to have its assumptions broken. And I am not at all a fan of this aspect of ===
, so personally I am happy with this restriction. What do you think should be the semantics of ==?
I cannot think of a semantics for ==
which would not be surprising other than the semantics for ===
proposed here.
I think we still need a bit more text in the README to clarify this all. But the current README is indeed consistent with our conclusion here.
to clarify, what are you expecting for these? @bakkot @littledan
#{a:-0} === #{a:+0} // true or false?
Object.is(#{a:-0}, #{a:+0}) // true or false?
i would expect those two to be the same for every value except a literal -0/0, or a literal NaN, including records and tuples with any contents.
I am tempted to move that to an open question as there are possible ramifications on what we mean when we talk about deep equality.
@bakkot has advocated that these both return false, so we don't expand the set of objects which are weird under comparison. Personally, I am persuaded by this argument. I want to suggest that the README take an initial position here (such as @bakkot's suggestion) and point to this issue for further discussion.
@rickbutton, I think it is best if both of those are false
(and #{a:NaN} === #{a:NaN}
and #Object.is({a:NaN}, #{a:NaN})
are both true
).
But yeah, this probably merits its own discussion thread - the OP was about whether Object.is
should match ===
. I opened #65 to track it.
(Sorry @littledan! I was in the process of typing this comment when you replied.)
#65 covers the specific undecided point left here (how to handle -0
+0
NaN
), the remaining problem in this issue is @isiahmeadows original question of whether Object.is
should expose some kind of "pointer equality semantics". Given the conclusion of #54 and the discussion above, Object.is
semantics should not differ from ===
(ignoring the unresolved point in #65). I will close this soon if there aren't any objections.
Closing this per comment above. ๐