Es-discuss - several decimal discussions

Mark S. Miller erights at
Sun Aug 24 11:43:40 PDT 2008

First, I'd like to apologize to Sam and the other IBM folks regarding
moving the goal posts. While I have repeatedly stated that I would
prefer decimal not to go in at all, in recent ES3.1 phone calls it
seemed we were coming close enough to closure that I expressed
something along the lines of "I wish we hadn't invested the time we
have in decimal. But it seems like we're close enough to closure that
we should just get it finished. Waiting isn't going to make this any
easier." If we were as close to done as it seemed at the time, perhaps
this would have been a reasonable sentiment. After Waldemar's recent
posts and my reading up a bit more on decimal, I now realize I was
wildly optimistic. To the degree that the exercise seems to have moved
the goal posts on you, it may be largely my fault. I'm sorry for the

In any case, I'm glad we seem to be in all around agreement to pull
decimal completely from 3.1. This allows us to settle all remaining
decimal matters in a less hurried manner.

2008/8/24 Brendan Eich <brendan at>:
> Premature generalization without implementation and user experience is
> unwarranted. What would Object.eq(NaN, NaN) do, return true? Never!

Object.eq(NaN, NaN) should indeed return true.

> Would
> Object.eq(-0, 0) return false? There's no purpose for this in the absence of
> evidence.

Object.eq(-0, 0) should indeed return false. The evidence from other
languages and from math itself is quite strong.

> I agree with you, compareTotal or something like it (stringization
> followed by ===) is enough.

compareTotal is addressing a completely different need than Object.eq.

With decimal postponed, we don't need to settle this now. But
JavaScript has no well behaved *equality* operator. As
<> explains, for a
predicate P to be an equivalence relationship (and thereby to define
equivalence classes), it should be
* reflexive: forall x: P(x,x)
* symmetric: forall x,y: P(x,y) implies P(y,x)
* transitive: forall x,y,z: P(x,y) & P(y,z) implies P(x,z)

* == is not reflexive or transitive. In the Caja project, when we have
occasionally violated our own style and used ==, we've always
regretted it.
* === is not reflexive. Fortunately, there's only one value on which
it isn't, NaN, so code picking off this special case can guard uses of
=== which is otherwise well behaved.

For code that picks off one additional special case, -0, remaining
uses of === are even more well behaved. What's the definition of
*equality* we all learned in grade school? "Substitution of equals for
equals does not change the meaning of the expression." Leaving aside
-0, for all other values in JavaScript today, if x === y, then x and y
and computationally indistinguishable. If you snapshot a computation,
substitute some occurrences of x for y, and resume, it would make no
observable difference. I expect that Harmony will have some kind of
identity-map (hashtable) abstraction, and probably some kind of
identity-hashcode that goes along with it. What identity comparison
should these be based on? Without a guarantee of indistinguishability,
you can't use such maps for transparent memoizing caches or
structure-sharing low-level serialization.

So today, if one wants a predicate that's both an equivalence
relationship and guarantees computational indistinguishability, one
can test for NaN and -0, and then use === for the remaining cases.
(This is also the case for Java's "==".) But if we expect 1.0m !==
1.00m in Harmony, then this will break such code. The language itself
should provide a strong equality operation that the language promises
not to break in future upgrades.

The most popular of Lisp's equality predicates, EQ, is indeed both an
equivalence relationship and implies a guarantee of computational
indistinguishability. It also has the longest history of robust use in
the Lisp community.


More information about the Es-discuss mailing list