You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `tuple` function takes any number of arguments and returns a unique, immutable object that inherits from `tuple.prototype` and is guaranteed to be `===` any other `tuple` object created from the same sequence of arguments:
The `tuple` object has a fixed numeric `.length` property, and its elements may be accessed using array index notation:
47
51
48
52
```js
@@ -52,6 +56,8 @@ t1.forEach((x, i) => {
52
56
});
53
57
```
54
58
59
+
### Nested `tuple`s
60
+
55
61
Since `tuple` objects are just another kind of JavaScript object, naturally `tuple`s can contain other `tuple`s:
56
62
57
63
```js
@@ -68,6 +74,8 @@ assert.strictEqual(
68
74
69
75
However, because tuples are immutable and always distinct from any of their arguments, it is not possible for a `tuple` to contain itself, nor to contain another `tuple` that contains the original `tuple`, and so forth.
70
76
77
+
### Constant time `===` equality
78
+
71
79
Since `tuple` objects are identical when (and only when) their elements are identical, any two tuples can be compared for equality in constant time, regardless of how many elements they contain.
72
80
73
81
This behavior also makes `tuple` objects useful as keys in a `Map`, or elements in a `Set`, without any extra hashing or equality logic:
@@ -87,6 +95,8 @@ if (info) {
87
95
}
88
96
```
89
97
98
+
### `Array` methods
99
+
90
100
Every non-destructive method of `Array.prototype` is supported by `tuple.prototype`, including `sort` and `reverse`, which return a modified copy of the `tuple` without altering the original:
91
101
92
102
```js
@@ -106,6 +116,8 @@ assert.strictEqual(
106
116
);
107
117
```
108
118
119
+
### Shallow immutability
120
+
109
121
While the identity, number, and order of elements in a `tuple` is fixed, please note that the contents of the individual elements are not frozen in any way:
Every `tuple` object is array-like and iterable, so `...` spreading and destructuring work as they should:
132
+
133
+
```js
134
+
func(...tuple(a, b));
135
+
func.apply(this, tuple(c, d, e));
136
+
137
+
assert.deepEqual(
138
+
[1, ...tuple(2, 3), 4],
139
+
[1, 2, 3, 4]
140
+
);
141
+
142
+
assert.strictEqual(
143
+
tuple(1, ...tuple(2, 3), 4),
144
+
tuple(1, 2, 3, 4)
145
+
);
146
+
147
+
const [a, [_, b]] =tuple(1, tuple(2, 3), 4);
148
+
assert.strictEqual(a, 1);
149
+
assert.strictEqual(b, 3);
150
+
```
151
+
152
+
### `tuple.isTuple(value)`
153
+
154
+
Since the `immutable-tuple` package could be installed multiple times in an application, there is no guarantee that the `tuple` constructor or `tuple.prototype` will be unique, so `value instanceof tuple` is unreliable. Instead, to test if a value is a `tuple`, you should use `tuple.isTuple(value)`.
155
+
156
+
Fortunately, even if your application uses multiple different `tuple` constructors from different copies of this library, the resulting `tuple` instances will still be `===` each other when their elements are the same. This is especially convenient given that this library provides both a CommonJS bundle and an ECMAScript module bundle, and some module systems might accidentally load those bundles simultaneously.
157
+
158
+
159
+
## Implementation details
118
160
119
161
Thanks to [Docco](http://ashkenas.com/docco/), you can read my implementation comments side-by-side with the actual code by visiting [the GitHub pages site](https://benjamn.github.io/immutable-tuple/) for this repository.
120
162
121
-
### Garbage collection
163
+
### Instance pooling (internalization)
122
164
123
165
Any data structure that guarantees `===` equality based on structural equality must maintain some sort of internal pool of previously encountered instances.
124
166
@@ -148,6 +190,8 @@ function tuple(...items) {
148
190
149
191
This implementation is pretty good, because it requires only linear time (_O_(`items.length`)) to determine if a `tuple` has been created previously for the given `items`, and you can't do better than linear time (asymptotically speaking) because you have to look at all the items. This code is also useful as an illustration of exactly how the `tuple` constructor behaves, in case you weren't satisfied by my examples in the previous section.
150
192
193
+
### Garbage collection
194
+
151
195
However, this simple implementation has a serious problem: in a garbage-collected language like JavaScript, the `pool` itself will retain references to all `tuple` objects ever created, which prevents `tuple` objects and their elements (which may be very large objects) from ever being reclaimed by the garbage collector, even after they become unreachable by any other means. In other words, storing objects in this kind of `tuple` would inevitably cause **memory leaks**.
152
196
153
197
To solve this problem, it's tempting to try changing `Map` to [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) here:
0 commit comments