tc39/proposal-record-tuple

`Object.is` semantics?

dead-claudia opened this issue ยท 15 comments

Edit: clarity.

Two questions on this subject:

  1. Should Object.is carry pointer equality semantics or === semantics?
  2. 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:

  1. Pointer equality.
  2. (a => Object.is(a, a))(o) must return true for every const value o, Object.is(a, b) must return false if a !== b or if a and b 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. ๐ŸŽ‰