Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.

Commit b0e03ef

Browse files
authored
Merge pull request #43 from mheiber/equality-clarification
clarify equality
2 parents 26dcc82 + 6773ac9 commit b0e03ef

File tree

1 file changed

+53
-15
lines changed

1 file changed

+53
-15
lines changed

README.md

+53-15
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,51 @@ record with ["a"]["b"] = 1
216216

217217
The same runtime verification will apply. It is a `TypeError` when a value inside a `Record` or `Tuple` is updated with a non-value type.
218218

219-
# `Record` and `Tuple` boxing objects
219+
# Equality
220220

221-
We add to the global namespace two boxing objects that you can use to manipulate those value types. Those boxing objects have multiple properties that are in line with how those value types behave.
221+
Instances of `Record` and `Tuple` are immutable, so their equality works like that of other immutable JS values like `boolean` and `string` instances:
222+
223+
```js
224+
assert(#{ a: 1 } === #{ a: 1 });
225+
assert(Object(#{ a: 1 }) !== Object(#{ a: 1 }));
226+
assert({ a: 1 } !== { a: 1 });
227+
```
228+
229+
This is distinct from how equality works for JS objects: `assert({} !== {});`. Strict comparison of objects will observe that each object is distinct.
230+
231+
`Record` and `Tuple` types are completely and deeply constant, if they have the same values stored, they will be considered strictly equal.
232+
233+
[Each of the four JS equality algorithms](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) gives the same result when comparing records or tuples:
234+
235+
```js
236+
// strict equality
237+
assert(#{ a: 1} === #{ a: 1 });
238+
assert(#[1] === #[1]);
239+
240+
// abstract equality comparison
241+
assert(#{ a: 1} == #{ a: 1 });
242+
assert(#[1] == #[1]);
243+
244+
// SameValue0
245+
assert(new Map().set(#{ a: 1 }, true).get(#{ a: 1 }));
246+
assert(new Map().set(#[1], true).get(#[1]));
247+
248+
// SameValue
249+
assert(Object.is(#{ a: 1}, #{ a: 1 }));
250+
assert(Object.is(#[1], #[1]));
251+
```
252+
253+
It is an **open question** whether two `Record`s with distinct insertion order are equal. We will gather additional feedback before proceeding:
254+
255+
```js
256+
assert(#{ a: 1, b: 2 } === #{ b: 2, a: 1 }); // not yet specified whether this passes
257+
```
258+
259+
This is related to [Ordering of properties](#ordering-of-properties).
260+
261+
# `Record` and `Tuple` Globals
262+
263+
We add to the global namespace two objects that you can use to manipulate records and tuples. Those objects have multiple properties that are in line with how records and tuples behave.
222264

223265
## Instantiation and converting from non-const types
224266

@@ -257,7 +299,7 @@ See the [appendix](./NS-Proto-Appendix.md) to learn more about the `Record` & `T
257299

258300
## Ordering of properties
259301

260-
This part is an **open question**, we did not decide yet what is going to be the behavior and will try to gather additional feedback before proceeding:
302+
This part is an **open question**. We will gather additional feedback before deciding.
261303

262304
### Alphabetical Order (option 1)
263305

@@ -458,18 +500,6 @@ let record2 = record with .c = 3;
458500
record2 = record2 with .a = 3, .b = 3;
459501
```
460502

461-
## `Record`/`Tuple` equality vs normal equality
462-
463-
```js
464-
assert(#{ a: 1 } === #{ a: 1 });
465-
assert(Object(#{ a: 1 }) !== Object(#{ a: 1 }));
466-
assert({ a: 1 } !== { a: 1 });
467-
```
468-
469-
Since we established that these value types are completely and deeply constant, if they have the same values stored, they will be considered strictly equal.
470-
471-
It is not the case with normal objects, those objects are instantiated in memory and strict comparison will see that both objects are located at different addresses, they are not strictly equal.
472-
473503
## What about const classes?
474504

475505
"Const" classes are being considered as a followup proposal that would let us associate methods to `Records`.
@@ -493,6 +523,14 @@ If const classes are standardized, features like [Temporal Proposal](https://git
493523

494524
The main difference is that this proposal has a proper assignment operation using `with`. This difference makes it possible to handle proper type support, which was not possible with the former proposal.
495525

526+
## Are there boxed versions of `Record` and `Tuple`?
527+
528+
Not sure yet! Two options:
529+
- `Object(record)` creates a `Record` instance where `Object(#{}) !== Object(#{})`. This is akin to how `Object(true)` creates a `Boolean` instance such that `Object(true) !== Object(true)`.
530+
- `Object(record)` returns `{}`. This is the same behavior as for `Object(null)` and `Object(undefined)`.
531+
532+
> Thanks @ljharb for raising this question.
533+
496534
## Would those matters be solved by a library and operator overloading?
497535

498536
Not quite since the `with` operation does some more advanced things such as being able to deeply change and return a value, for instance:

0 commit comments

Comments
 (0)