Most non-legacy things within the spec currently, including Map, Set, and Array.prototype.includes, use SameValueZero, which is like Object.is, except it treats +0 and -0 as identical. Is there a reason this doesn't do the same?
my 2 cents: imo using SameValueZero there was a mistake - it makes Maps and Sets not Functors (and it makes it impossible to build a subclass that robustly doesn't treat +0 and -0 the same). It's easy to treat them the same - what's hard is treating them differently - so the spec should imo be treating them differently.
@ljharb Sets can't be functors no matter what their keys are - there's no way to define a generic, structure-preserving map, because there's always the possibility of new duplicates getting lost. Maps can only be functors given a known set of keys, but:
You can still iterate them, but being a functor isn't a requirement for being iterable.
FWIW, Haskell maps and sets are defined like this:
I probably shouldn't have even mentioned functors - simply the fact that you can't build a more discriminating subclass is why the base class should have differentiated between -0 and +0.
Who says you couldn't override all the methods and add an extra private
field? Boilerplatey, but it works, and I've done similar in the past when I
needed to override some internal behavior.
On Thu, Sep 13, 2018 at 02:27 Jordan Harband notifications@github.com
wrote:
I probably shouldn't have even mentioned functors - simply the fact that
you can't build a more discriminating subclass is why the base class should
have differentiated between -0 and +0.—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/tc39/proposal-pattern-matching/issues/121#issuecomment-420898009,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBPRdN-aFeG44YkWwHCnJoyT9j3Ubks5uafrngaJpZM4WmkhA
.
@isiahmeadows because Map.prototype.set.call on a subclass will always conflate -0 and +0.
Not if you check beforehand that 1/x === -1/0 and use the private property
for the value in that case instead of delegating...
On Thu, Sep 13, 2018 at 03:01 Jordan Harband notifications@github.com
wrote:
@isiahmeadows https://github.com/isiahmeadows because
Map.prototype.set.call on a subclass will always conflate -0 and +0.—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/tc39/proposal-pattern-matching/issues/121#issuecomment-420904675,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBOFHhlVMHVygHO-iSuPHRo80m_tCks5uagKOgaJpZM4WmkhA
.
@isiahmeadows Note that the comment you're responding to was about Map.prototype.set.call(customMap, ...). That bypasses your overridden methods; there's no way to interpose a check against that.
(Unless you just ignore your own MapData entirely and store all of your stuff in an additional private Map; then using the original Map#get/set would just be doing some nonsense work.)
@ljharb @isiahmeadows Somebody has already created SameValueSet, a set that is backed by an ECMAScript Set but effectively uses SameValue for discrimination instead of SameValueZero. It's order-preserving and everything. The same can be done for Maps.
I don't see Map.prototype.set.call(customMap, ...) as a valid use since they're different things. It's as nonsensical as RegExp.prototype.test.call(customMap, ...).
@michaelficarra This is effectively what I was saying, just better put. 👍
If it’s a Map subclass, then borrowing the base method and .calling on it is an idomatic robustness technique; your library extends Set, so it’s entirely sensible to borrow a Set method to .call on it - and these would fail on your library. It’s great that you wrote this, but the caveats are exactly why SameValueZero was the wrong choice for Map and Set.
I would prefer to never again use SameValueZero in the language, wherever consistency/precedent permits.
@ljharb You're right, if it extends Set/Map, you should be able to use the base method on the children. SameValueSet extending Set was a leftover part from an earlier design. I will change it to extend Object instead.
I would prefer to never again use SameValueZero in the language, wherever consistency/precedent permits.
Agreed, though I expect you'll see the consistency argument used in a way you don't think is appropriate.
The updated proposal (#174) uses SameValueZero semantics. However, whether it uses SameValueZero or SameValue remains an open question, to resolve prior to stage 3.
The updated proposal (#174) uses
SameValueZerosemantics. However, whether it usesSameValueZeroorSameValueremains an open question, to resolve prior to stage 3.
In the updated proposal I see that - is treated special as a part of literals and -Infinity. I dunno if it would be too confusing or not but it could be the case that -0 is explictly written as such, it only matches -0.
i.e.
const kind = (v) => match (v) {
when (-0) { "minus-zero" }
when (0) { "zero" }
else { "other" }
}
kind(-0); // minus-zero
kind(0); // zero
One could even have three-typed -0, +0 and 0, the first two of which are strict, and 0 which is simply either.
Alternatively we could have a couple of builtin methods/patterns of Number that check for minus/positive zero, then we could pin them:
Number.isNegativeZero = function isNegativeZero(value) {
return Object.is(value, -0);
}
Number.isNegativeZero[Symbol.matcher] = function(value) {
return { matched: Number.isNegativeZero(value), value };
}
Number.isPositiveZero = function isPositiveZero(value) {
return Object.is(value, +0);
}
Number.isPositiveZero[Symbol.matcher] = function(value) {
return { matched: Number.isPositiveZero(value), value };
}
const kind = (v) => match (v) {
when (^Number.isPositiveZero) { "positive-zero" }
when (^Number.isNegativeZero) { "negative-zero" }
when (0) { "any-zero" } // Can't actually be reached as previous two functions cover all zeros
}
I agree that if we keep SameValueZero, that it doesn’t make as much sense to allow a signed zero as a pattern - but i still hope for it to use SameValue.
Most helpful comment
@ljharb @isiahmeadows Somebody has already created
SameValueSet, a set that is backed by an ECMAScriptSetbut effectively usesSameValuefor discrimination instead ofSameValueZero. It's order-preserving and everything. The same can be done forMaps.I don't see
Map.prototype.set.call(customMap, ...)as a valid use since they're different things. It's as nonsensical asRegExp.prototype.test.call(customMap, ...).