New topic regarding Proxies: intercession for ===

Brendan Eich brendan at
Wed Oct 27 14:09:37 PDT 2010

David Ungar raised this as a question from the audience after Tom's Proxies talk at DLS. One would expect no less from David, who indeed cited Self, which allows more intercession than harmony:proxies enables.

This is not something I'm trying to get into harmony:proxies, but I thought it deserved more discussion, so here in es-discuss seems like a good place.

One reason not to allow === to be trapped is mutation. If two object references are ===, then today we know they reference the same object. If that object is not frozen, then we expect to see effects through both references. If frozen, no effects can be committed or viewed via any reference.

If unfixed proxies could be === to unfrozen objects, then the proxy's handler could do whatever it wants and violate these old semantics.

The value types idea, building on proxies, will want to support a value proxy that can intercede for === and most of the other operators. See (which is a tour de force that covers other applications than value types!).

But value types, we think, would be frozen and compared by contents -- property names and property values, recursively down the typically-shallow, frozen tree that represents the value. Details TBD, but this solves the mutation issue.

So perhaps the answer to David's DLS question is twofold: "we chickened out for now; we're fixing for a subset of all objects later (maybe)".

Still not the crisp and Self-ish answer one might hope for, but that is JS :for you :-/. So I went back to the Self well:

4.8 Equality, Identity, and Indistinguishability

Equality, identity, and indistinguishability are three related concepts that are often confused. Two objects are equal if they “mean the same thing”. For example, 3 = 3.0 even though they are different objects and have different representations. Two objects are identical if and only if they are the same object. (Or, more precisely, two references are identical if they refer to the same object.) The primitive _Eq: tests if two objects are identical. Finally, two objects are indistinguishable if they have exactly the same behavior for every possible sequence of non-reflective messages. The binary operator “==” tests for indistinguishability. Identity implies indistinguishability which implies equality.

It is actually not possible to guarantee that two different objects are indistinguishable, since reflection could be used to modify one of the objects to behave differently after the indistinguisability test was made. Thus, == is defined to mean identity by default. Mirrors, however, override this default behavior; (m1 == m2) if (m1 reflectee _Eq: m2 reflectee). This makes it appear that there is at most one mirror object for each object in the system. This illusion would break down, however, if one added mutable state to mirror objects.


For JS, we don't have a clean equality analogue. One might be tempted to say that equality is ==, identity is === (ignoring -0 === 0 and NaN !== NaN), and indistinguishability is Object.eq (name still not settled on), from

But JS == is not even an equivalence relation, and -0 is not identical to 0 operationally even if one buys into the IEEE-754 standard and numerical programming precedents for NaN !== NaN.

So it is more accurate to say JS has === for equality, it can have Object.eq for identity (self-hosted today on top of ===), and it *could* have indistinguishability.

Should we consider indistinguishability on the Self model, with proxies instead of mirrors, and any other necessary changes?

JS will never be as simple as Self, but with proxies and value types based on them, it seems we might have get very close to the "right" answer to David's question.


More information about the es-discuss mailing list