On 4/2/2014 8:01 AM, Andreas Rossberg wrote:
That is very helpful, thanks! I agree with a lot with what you say.
But to expand on my reply to your blog post, I have one fundamental
concern: I think the idea that value types should be objects would
require stretching the notion of object too far, and violate one of
the fundamental properties that objects currently have. Namely,
objects have generative identity.

...

Either way, I think we should refrain from introducing a completely
new, hybrid form of value that behaves neither like a primitive nor
like a proper object. To me, it seems a much more elegant and economic
model to extend the notion of primitive type. That is, make value
types primitive-like, use the existing wrapping semantics, let them
have an implicit prototype link, and typeof different from "object"
(whether something fixed or actually user-defined is debatable).

It seems like we're trying to have our cake and eat it too; we want these binary data objects to act both like primitives and objects at the same time. We want them to be comparable by value, but we also want them to be mutable. The second article proposes doing this by drawing a line in the sand between mutable object-like versions of a Type and immutable primitive-like versions of a Type. I think this is problematic because it seems like a kludge to get something kinda-sorta like what we want but not really, and also because it introduces two things that look very similar but that act completely different when it comes to identity.

```js
const Color = new StructType({ red: uint8, green: uint8, blue: uint8 });
const ColorV = Color.valueType();

const blue = Color({ blue: 255 });
blue === Color({ blue: 255 }); // false

const bluev = Color({ blue: 255 });
bluev === ColorV({ blue: 255 }); // true

blue === bluev; // false

// I would expect to end up needing helpers like:
function eq(a, b) {
  var TypeV = a.constructor.valueType();
  return TypeV(a) === TypeV(b); // eww
}

eq(blue, bluev); // true
```


What I *really* want to be able to do is something like:

```js
const red = Object.freeze(Color({ red: 255 })); // immutable
const blue = Object.freeze(Color({ blue: 255 })); // immutable
let myColor = Color({ red: 255 }); // mutable
myColor === red; // true
myColor.red = 0;
myColor.blue = 255;
myColor === blue; // true, OOPS new identity!
```

Making Color produce either objects or primitives is going to break strong existing invariants. If it makes objects then it breaks invariants about object identity. If it makes primitives then it breaks the invariant that primitives don't have mutable state. For either, it breaks the invariant that for any two values A and B, the result of doing `A === B` will never change. I don't think we can/should violate any of the above invariants and so that leaves us with two options: reject mutable value types, or give up on using `===` to structurally compare them. Choosing the latter seems to naturally lead to the idea of introducing a structural comparison operator.

If we introduced a new configurable equality operator we might be able to find a path out of this mess. For the purpose of example, let's name this operator EQ for now. I imagine `EQ` is to `===` as `for-of` is to `for-in`. With for-in and for-of, they both are about iterating over an object, but they define "iteration" very differently. With === and EQ, they both are about comparing the equality of an object, but they define "equality" differently.

Since === already has identity covered, EQ should focus on structural comparisons. I would expect to see it working something like:
```js
[5, 10, 20] EQ [5, 10, 20]; // true
({ x: 10 } EQ { x: 10 }); // true
({ x: 20 } EQ { x: 10 }); // false
true EQ true; // true

// from above
let myColor = Color({ red: 255 }); // mutable
myColor === red; // false
myColor EQ red; // true
myColor.red = 0;
myColor.blue = 255;
myColor EQ blue; // true
```

This also opens up the door to how comparing different numeric value types can work:
```js
0L === 0; // false
0L EQ 0; // true
```


I know it's cringe-worthy, adding more operators for something that is ostensibly already well covered by JS, with its already two equality operators and another (or two?) definitions of equality used in the spec. But really, all the existing operators are inextricably linked with identity and having nothing to do with structural comparison, so this really is a different kind of thing.
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to