immutable 4.0.0-rc.1 → 4.0.0-rc.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
- Immutable collections for JavaScript
2
- ====================================
1
+ # Immutable collections for JavaScript
3
2
 
4
- [![Build Status](https://travis-ci.org/facebook/immutable-js.svg?branch=master)](https://travis-ci.org/facebook/immutable-js)
3
+ [![Build Status](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml?query=branch%3Amain) [Chat on slack](https://immutable-js.slack.com)
5
4
 
6
5
  [Immutable][] data cannot be changed once created, leading to much simpler
7
6
  application development, no defensive copying, and enabling advanced memoization
@@ -16,22 +15,20 @@ These data structures are highly efficient on modern JavaScript VMs by using
16
15
  structural sharing via [hash maps tries][] and [vector tries][] as popularized
17
16
  by Clojure and Scala, minimizing the need to copy or cache data.
18
17
 
19
- `Immutable` also provides a lazy `Seq`, allowing efficient
18
+ Immutable.js also provides a lazy `Seq`, allowing efficient
20
19
  chaining of collection methods like `map` and `filter` without creating
21
20
  intermediate representations. Create some `Seq` with `Range` and `Repeat`.
22
21
 
23
22
  Want to hear more? Watch the presentation about Immutable.js:
24
23
 
25
- <a href="https://youtu.be/I7IdS-PbEgI" target="_blank" alt="Immutable Data and React"><img src="https://img.youtube.com/vi/I7IdS-PbEgI/0.jpg" /></a>
24
+ [![Immutable Data and React](website/public/Immutable-Data-and-React-YouTube.png)](https://youtu.be/I7IdS-PbEgI)
26
25
 
27
- [Persistent]: http://en.wikipedia.org/wiki/Persistent_data_structure
28
- [Immutable]: http://en.wikipedia.org/wiki/Immutable_object
29
- [hash maps tries]: http://en.wikipedia.org/wiki/Hash_array_mapped_trie
30
- [vector tries]: http://hypirion.com/musings/understanding-persistent-vector-pt-1
26
+ [Persistent]: https://en.wikipedia.org/wiki/Persistent_data_structure
27
+ [Immutable]: https://en.wikipedia.org/wiki/Immutable_object
28
+ [hash maps tries]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
29
+ [vector tries]: https://hypirion.com/musings/understanding-persistent-vector-pt-1
31
30
 
32
-
33
- Getting started
34
- ---------------
31
+ ## Getting started
35
32
 
36
33
  Install `immutable` using npm.
37
34
 
@@ -39,70 +36,102 @@ Install `immutable` using npm.
39
36
  npm install immutable
40
37
  ```
41
38
 
39
+ Or install using yarn.
40
+
41
+ ```shell
42
+ yarn add immutable
43
+ ```
44
+
42
45
  Then require it into any module.
43
46
 
44
- ```javascript
45
- var Immutable = require('immutable');
46
- var map1 = Immutable.Map({a:1, b:2, c:3});
47
- var map2 = map1.set('b', 50);
48
- map1.get('b'); // 2
49
- map2.get('b'); // 50
47
+ <!-- runkit:activate -->
48
+
49
+ ```js
50
+ const { Map } = require('immutable');
51
+ const map1 = Map({ a: 1, b: 2, c: 3 });
52
+ const map2 = map1.set('b', 50);
53
+ map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
50
54
  ```
51
55
 
52
56
  ### Browser
53
57
 
54
- To use `immutable` from a browser, download [dist/immutable.min.js](https://github.com/facebook/immutable-js/blob/master/dist/immutable.min.js)
55
- or use a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
56
- or [jsDelivr](http://www.jsdelivr.com/#!immutable.js).
58
+ Immutable.js has no dependencies, which makes it predictable to include in a Browser.
59
+
60
+ It's highly recommended to use a module bundler like [webpack](https://webpack.github.io/),
61
+ [rollup](https://rollupjs.org/), or
62
+ [browserify](https://browserify.org/). The `immutable` npm module works
63
+ without any additional consideration. All examples throughout the documentation
64
+ will assume use of this kind of tool.
57
65
 
58
- Then, add it as a script tag to your page:
66
+ Alternatively, Immutable.js may be directly included as a script tag. Download
67
+ or link to a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
68
+ or [jsDelivr](https://www.jsdelivr.com/package/npm/immutable).
69
+
70
+ Use a script tag to directly add `Immutable` to the global scope:
59
71
 
60
72
  ```html
61
73
  <script src="immutable.min.js"></script>
62
74
  <script>
63
- var map1 = Immutable.Map({a:1, b:2, c:3});
64
- var map2 = map1.set('b', 50);
65
- map1.get('b'); // 2
66
- map2.get('b'); // 50
75
+ var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
76
+ var map2 = map1.set('b', 50);
77
+ map1.get('b'); // 2
78
+ map2.get('b'); // 50
67
79
  </script>
68
80
  ```
69
81
 
70
- Or use an AMD loader (such as [RequireJS](http://requirejs.org/)):
82
+ Or use an AMD-style loader (such as [RequireJS](https://requirejs.org/)):
71
83
 
72
- ```javascript
84
+ ```js
73
85
  require(['./immutable.min.js'], function (Immutable) {
74
- var map1 = Immutable.Map({a:1, b:2, c:3});
75
- var map2 = map1.set('b', 50);
76
- map1.get('b'); // 2
77
- map2.get('b'); // 50
86
+ var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
87
+ var map2 = map1.set('b', 50);
88
+ map1.get('b'); // 2
89
+ map2.get('b'); // 50
78
90
  });
79
91
  ```
80
92
 
81
- If you're using [browserify](http://browserify.org/), the `immutable` npm module
82
- also works from the browser.
83
-
84
- ### TypeScript
93
+ ### Flow & TypeScript
85
94
 
86
95
  Use these Immutable collections and sequences as you would use native
87
- collections in your [TypeScript](http://typescriptlang.org) programs while still taking
96
+ collections in your [Flowtype](https://flowtype.org/) or [TypeScript](https://typescriptlang.org) programs while still taking
88
97
  advantage of type generics, error detection, and auto-complete in your IDE.
89
98
 
90
- Just add a reference with a relative path to the type declarations at the top
91
- of your file.
99
+ Installing `immutable` via npm brings with it type definitions for Flow (v0.55.0 or higher)
100
+ and TypeScript (v2.1.0 or higher), so you shouldn't need to do anything at all!
92
101
 
93
- ```javascript
102
+ #### Using TypeScript with Immutable.js v4
103
+
104
+ Immutable.js type definitions embrace ES2015. While Immutable.js itself supports
105
+ legacy browsers and environments, its type definitions require TypeScript's 2015
106
+ lib. Include either `"target": "es2015"` or `"lib": "es2015"` in your
107
+ `tsconfig.json`, or provide `--target es2015` or `--lib es2015` to the
108
+ `tsc` command.
109
+
110
+ <!-- runkit:activate -->
111
+
112
+ ```js
113
+ const { Map } = require('immutable');
114
+ const map1 = Map({ a: 1, b: 2, c: 3 });
115
+ const map2 = map1.set('b', 50);
116
+ map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
117
+ ```
118
+
119
+ #### Using TypeScript with Immutable.js v3 and earlier:
120
+
121
+ Previous versions of Immutable.js include a reference file which you can include
122
+ via relative path to the type definitions at the top of your file.
123
+
124
+ ```js
94
125
  ///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
95
- import Immutable = require('immutable');
126
+ import Immutable from require('immutable');
96
127
  var map1: Immutable.Map<string, number>;
97
- map1 = Immutable.Map({a:1, b:2, c:3});
128
+ map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
98
129
  var map2 = map1.set('b', 50);
99
130
  map1.get('b'); // 2
100
131
  map2.get('b'); // 50
101
132
  ```
102
133
 
103
-
104
- The case for Immutability
105
- -------------------------
134
+ ## The case for Immutability
106
135
 
107
136
  Much of what makes application development difficult is tracking mutation and
108
137
  maintaining state. Developing with immutable data encourages you to think
@@ -121,23 +150,25 @@ and especially well with an application designed using the ideas of [Flux][].
121
150
  When data is passed from above rather than being subscribed to, and you're only
122
151
  interested in doing work when something has changed, you can use equality.
123
152
 
124
- Immutable collections should be treated as *values* rather than *objects*. While
153
+ Immutable collections should be treated as _values_ rather than _objects_. While
125
154
  objects represent some thing which could change over time, a value represents
126
155
  the state of that thing at a particular instance of time. This principle is most
127
156
  important to understanding the appropriate use of immutable data. In order to
128
157
  treat Immutable.js collections as values, it's important to use the
129
- `Immutable.is()` function or `.equals()` method to determine value equality
130
- instead of the `===` operator which determines object reference identity.
131
-
132
- ```javascript
133
- var map1 = Immutable.Map({a:1, b:2, c:3});
134
- var map2 = map1.set('b', 2);
135
- assert(map1.equals(map2) === true);
136
- var map3 = map1.set('b', 50);
137
- assert(map1.equals(map3) === false);
158
+ `Immutable.is()` function or `.equals()` method to determine _value equality_
159
+ instead of the `===` operator which determines object _reference identity_.
160
+
161
+ <!-- runkit:activate -->
162
+
163
+ ```js
164
+ const { Map } = require('immutable');
165
+ const map1 = Map({ a: 1, b: 2, c: 3 });
166
+ const map2 = Map({ a: 1, b: 2, c: 3 });
167
+ map1.equals(map2); // true
168
+ map1 === map2; // false
138
169
  ```
139
170
 
140
- Note: As a performance optimization `Immutable` attempts to return the existing
171
+ Note: As a performance optimization Immutable.js attempts to return the existing
141
172
  collection when an operation would result in an identical collection, allowing
142
173
  for using `===` reference equality to determine if something definitely has not
143
174
  changed. This can be extremely useful when used within a memoization function
@@ -145,48 +176,62 @@ which would prefer to re-run the function if a deeper equality check could
145
176
  potentially be more costly. The `===` equality check is also used internally by
146
177
  `Immutable.is` and `.equals()` as a performance optimization.
147
178
 
179
+ <!-- runkit:activate -->
180
+
181
+ ```js
182
+ const { Map } = require('immutable');
183
+ const map1 = Map({ a: 1, b: 2, c: 3 });
184
+ const map2 = map1.set('b', 2); // Set to same value
185
+ map1 === map2; // true
186
+ ```
187
+
148
188
  If an object is immutable, it can be "copied" simply by making another reference
149
189
  to it instead of copying the entire object. Because a reference is much smaller
150
190
  than the object itself, this results in memory savings and a potential boost in
151
191
  execution speed for programs which rely on copies (such as an undo-stack).
152
192
 
153
- ```javascript
154
- var map1 = Immutable.Map({a:1, b:2, c:3});
155
- var clone = map1;
193
+ <!-- runkit:activate -->
194
+
195
+ ```js
196
+ const { Map } = require('immutable');
197
+ const map = Map({ a: 1, b: 2, c: 3 });
198
+ const mapCopy = map; // Look, "copies" are free!
156
199
  ```
157
200
 
158
- [React]: http://facebook.github.io/react/
159
- [Flux]: http://facebook.github.io/flux/docs/overview.html
201
+ [React]: https://reactjs.org/
202
+ [Flux]: https://facebook.github.io/flux/docs/in-depth-overview/
160
203
 
161
204
 
162
- JavaScript-first API
163
- --------------------
205
+ ## JavaScript-first API
164
206
 
165
- While `immutable` is inspired by Clojure, Scala, Haskell and other functional
207
+ While Immutable.js is inspired by Clojure, Scala, Haskell and other functional
166
208
  programming environments, it's designed to bring these powerful concepts to
167
209
  JavaScript, and therefore has an Object-Oriented API that closely mirrors that
168
- of [ES6][] [Array][], [Map][], and [Set][].
210
+ of [ES2015][] [Array][], [Map][], and [Set][].
169
211
 
170
- [ES6]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
171
- [Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
172
- [Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
173
- [Set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
212
+ [es2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
213
+ [array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
214
+ [map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
215
+ [set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
174
216
 
175
217
  The difference for the immutable collections is that methods which would mutate
176
- the collection, like `push`, `set`, `unshift` or `splice` instead return a new
177
- immutable collection. Methods which return new arrays like `slice` or `concat`
218
+ the collection, like `push`, `set`, `unshift` or `splice`, instead return a new
219
+ immutable collection. Methods which return new arrays, like `slice` or `concat`,
178
220
  instead return new immutable collections.
179
221
 
180
- ```javascript
181
- var list1 = Immutable.List.of(1, 2);
182
- var list2 = list1.push(3, 4, 5);
183
- var list3 = list2.unshift(0);
184
- var list4 = list1.concat(list2, list3);
185
- assert(list1.size === 2);
186
- assert(list2.size === 5);
187
- assert(list3.size === 6);
188
- assert(list4.size === 13);
189
- assert(list4.get(0) === 1);
222
+ <!-- runkit:activate -->
223
+
224
+ ```js
225
+ const { List } = require('immutable');
226
+ const list1 = List([1, 2]);
227
+ const list2 = list1.push(3, 4, 5);
228
+ const list3 = list2.unshift(0);
229
+ const list4 = list1.concat(list2, list3);
230
+ assert.equal(list1.size, 2);
231
+ assert.equal(list2.size, 5);
232
+ assert.equal(list3.size, 6);
233
+ assert.equal(list4.size, 13);
234
+ assert.equal(list4.get(0), 1);
190
235
  ```
191
236
 
192
237
  Almost all of the methods on [Array][] will be found in similar form on
@@ -194,35 +239,51 @@ Almost all of the methods on [Array][] will be found in similar form on
194
239
  found on `Immutable.Set`, including collection operations like `forEach()`
195
240
  and `map()`.
196
241
 
197
- ```javascript
198
- var alpha = Immutable.Map({a:1, b:2, c:3, d:4});
242
+ <!-- runkit:activate -->
243
+
244
+ ```js
245
+ const { Map } = require('immutable');
246
+ const alpha = Map({ a: 1, b: 2, c: 3, d: 4 });
199
247
  alpha.map((v, k) => k.toUpperCase()).join();
200
248
  // 'A,B,C,D'
201
249
  ```
202
250
 
203
- ### Accepts raw JavaScript objects.
251
+ ### Convert from raw JavaScript objects and arrays.
252
+
253
+ Designed to inter-operate with your existing JavaScript, Immutable.js
254
+ accepts plain JavaScript Arrays and Objects anywhere a method expects a
255
+ `Collection`.
204
256
 
205
- Designed to inter-operate with your existing JavaScript, `immutable`
206
- accepts plain JavaScript Arrays and Objects anywhere a method expects an
207
- `Iterable` with no performance penalty.
257
+ <!-- runkit:activate -->
208
258
 
209
- ```javascript
210
- var map1 = Immutable.Map({a:1, b:2, c:3, d:4});
211
- var map2 = Immutable.Map({c:10, a:20, t:30});
212
- var obj = {d:100, o:200, g:300};
213
- var map3 = map1.merge(map2, obj);
259
+ ```js
260
+ const { Map, List } = require('immutable');
261
+ const map1 = Map({ a: 1, b: 2, c: 3, d: 4 });
262
+ const map2 = Map({ c: 10, a: 20, t: 30 });
263
+ const obj = { d: 100, o: 200, g: 300 };
264
+ const map3 = map1.merge(map2, obj);
214
265
  // Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }
266
+ const list1 = List([1, 2, 3]);
267
+ const list2 = List([4, 5, 6]);
268
+ const array = [7, 8, 9];
269
+ const list3 = list1.concat(list2, array);
270
+ // List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
215
271
  ```
216
272
 
217
- This is possible because `immutable` can treat any JavaScript Array or Object
218
- as an Iterable. You can take advantage of this in order to get sophisticated
273
+ This is possible because Immutable.js can treat any JavaScript Array or Object
274
+ as a Collection. You can take advantage of this in order to get sophisticated
219
275
  collection methods on JavaScript Objects, which otherwise have a very sparse
220
276
  native API. Because Seq evaluates lazily and does not cache intermediate
221
277
  results, these operations can be extremely efficient.
222
278
 
223
- ```javascript
224
- var myObject = {a:1,b:2,c:3};
225
- Immutable.Seq(myObject).map(x => x * x).toObject();
279
+ <!-- runkit:activate -->
280
+
281
+ ```js
282
+ const { Seq } = require('immutable');
283
+ const myObject = { a: 1, b: 2, c: 3 };
284
+ Seq(myObject)
285
+ .map(x => x * x)
286
+ .toObject();
226
287
  // { a: 1, b: 4, c: 9 }
227
288
  ```
228
289
 
@@ -230,69 +291,92 @@ Keep in mind, when using JS objects to construct Immutable Maps, that
230
291
  JavaScript Object properties are always strings, even if written in a quote-less
231
292
  shorthand, while Immutable Maps accept keys of any type.
232
293
 
294
+ <!-- runkit:activate -->
295
+
233
296
  ```js
234
- var obj = { 1: "one" };
235
- Object.keys(obj); // [ "1" ]
236
- obj["1"]; // "one"
237
- obj[1]; // "one"
238
-
239
- var map = Immutable.fromJS(obj);
240
- map.get("1"); // "one"
241
- map.get(1); // undefined
297
+ const { fromJS } = require('immutable');
298
+
299
+ const obj = { 1: 'one' };
300
+ console.log(Object.keys(obj)); // [ "1" ]
301
+ console.log(obj['1'], obj[1]); // "one", "one"
302
+
303
+ const map = fromJS(obj);
304
+ console.log(map.get('1'), map.get(1)); // "one", undefined
242
305
  ```
243
306
 
244
307
  Property access for JavaScript Objects first converts the key to a string, but
245
308
  since Immutable Map keys can be of any type the argument to `get()` is
246
309
  not altered.
247
310
 
248
-
249
311
  ### Converts back to raw JavaScript objects.
250
312
 
251
- All `immutable` Iterables can be converted to plain JavaScript Arrays and
313
+ All Immutable.js Collections can be converted to plain JavaScript Arrays and
252
314
  Objects shallowly with `toArray()` and `toObject()` or deeply with `toJS()`.
253
- All Immutable Iterables also implement `toJSON()` allowing them to be passed to
254
- `JSON.stringify` directly.
255
-
256
- ```javascript
257
- var deep = Immutable.Map({ a: 1, b: 2, c: Immutable.List.of(3, 4, 5) });
258
- deep.toObject() // { a: 1, b: 2, c: List [ 3, 4, 5 ] }
259
- deep.toArray() // [ 1, 2, List [ 3, 4, 5 ] ]
260
- deep.toJS() // { a: 1, b: 2, c: [ 3, 4, 5 ] }
261
- JSON.stringify(deep) // '{"a":1,"b":2,"c":[3,4,5]}'
315
+ All Immutable Collections also implement `toJSON()` allowing them to be passed
316
+ to `JSON.stringify` directly. They also respect the custom `toJSON()` methods of
317
+ nested objects.
318
+
319
+ <!-- runkit:activate -->
320
+
321
+ ```js
322
+ const { Map, List } = require('immutable');
323
+ const deep = Map({ a: 1, b: 2, c: List([3, 4, 5]) });
324
+ console.log(deep.toObject()); // { a: 1, b: 2, c: List [ 3, 4, 5 ] }
325
+ console.log(deep.toArray()); // [ 1, 2, List [ 3, 4, 5 ] ]
326
+ console.log(deep.toJS()); // { a: 1, b: 2, c: [ 3, 4, 5 ] }
327
+ JSON.stringify(deep); // '{"a":1,"b":2,"c":[3,4,5]}'
262
328
  ```
263
329
 
264
- ### Embraces ES6
330
+ ### Embraces ES2015
331
+
332
+ Immutable.js supports all JavaScript environments, including legacy
333
+ browsers (even IE11). However it also takes advantage of features added to
334
+ JavaScript in [ES2015][], the latest standard version of JavaScript, including
335
+ [Iterators][], [Arrow Functions][], [Classes][], and [Modules][]. It's inspired
336
+ by the native [Map][] and [Set][] collections added to ES2015.
337
+
338
+ All examples in the Documentation are presented in ES2015. To run in all
339
+ browsers, they need to be translated to ES5.
340
+
341
+ ```js
342
+ // ES2015
343
+ const mapped = foo.map(x => x * x);
344
+ // ES5
345
+ var mapped = foo.map(function (x) {
346
+ return x * x;
347
+ });
348
+ ```
265
349
 
266
- `Immutable` takes advantage of features added to JavaScript in [ES6][],
267
- the latest standard version of ECMAScript (JavaScript), including [Iterators][],
268
- [Arrow Functions][], [Classes][], and [Modules][]. It's also inspired by the
269
- [Map][] and [Set][] collections added to ES6. The library is "transpiled" to ES3
270
- in order to support all modern browsers.
350
+ All Immutable.js collections are [Iterable][iterators], which allows them to be
351
+ used anywhere an Iterable is expected, such as when spreading into an Array.
271
352
 
272
- All examples are presented in ES6. To run in all browsers, they need to be
273
- translated to ES3.
353
+ <!-- runkit:activate -->
274
354
 
275
355
  ```js
276
- // ES6
277
- foo.map(x => x * x);
278
- // ES3
279
- foo.map(function (x) { return x * x; });
356
+ const { List } = require('immutable');
357
+ const aList = List([1, 2, 3]);
358
+ const anArray = [0, ...aList, 4, 5]; // [ 0, 1, 2, 3, 4, 5 ]
280
359
  ```
281
360
 
361
+ Note: A Collection is always iterated in the same order, however that order may
362
+ not always be well defined, as is the case for the `Map` and `Set`.
363
+
282
364
  [Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
283
365
  [Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
284
- [Classes]: http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
285
- [Modules]: http://www.2ality.com/2014/09/es6-modules-final.html
366
+ [Classes]: https://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
367
+ [Modules]: https://www.2ality.com/2014/09/es6-modules-final.html
286
368
 
287
369
 
288
- Nested Structures
289
- -----------------
370
+ ## Nested Structures
290
371
 
291
- The collections in `immutable` are intended to be nested, allowing for deep
372
+ The collections in Immutable.js are intended to be nested, allowing for deep
292
373
  trees of data, similar to JSON.
293
374
 
294
- ```javascript
295
- var nested = Immutable.fromJS({a:{b:{c:[3,4,5]}}});
375
+ <!-- runkit:activate -->
376
+
377
+ ```js
378
+ const { fromJS } = require('immutable');
379
+ const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
296
380
  // Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }
297
381
  ```
298
382
 
@@ -300,92 +384,124 @@ A few power-tools allow for reading and operating on nested data. The
300
384
  most useful are `mergeDeep`, `getIn`, `setIn`, and `updateIn`, found on `List`,
301
385
  `Map` and `OrderedMap`.
302
386
 
303
- ```javascript
304
- var nested2 = nested.mergeDeep({a:{b:{d:6}}});
387
+ <!-- runkit:activate -->
388
+
389
+ ```js
390
+ const { fromJS } = require('immutable');
391
+ const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
392
+
393
+ const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });
305
394
  // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
306
395
 
307
- nested2.getIn(['a', 'b', 'd']); // 6
396
+ console.log(nested2.getIn(['a', 'b', 'd'])); // 6
308
397
 
309
- var nested3 = nested2.updateIn(['a', 'b', 'd'], value => value + 1);
398
+ const nested3 = nested2.updateIn(['a', 'b', 'd'], value => value + 1);
399
+ console.log(nested3);
310
400
  // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }
311
401
 
312
- var nested4 = nested3.updateIn(['a', 'b', 'c'], list => list.push(6));
402
+ const nested4 = nested3.updateIn(['a', 'b', 'c'], list => list.push(6));
313
403
  // Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
314
404
  ```
315
405
 
406
+ ## Equality treats Collections as Values
316
407
 
317
- Lazy Seq
318
- --------
319
-
320
- `Seq` describes a lazy operation, allowing them to efficiently chain
321
- use of all the Iterable methods (such as `map` and `filter`).
322
-
323
- **Seq is immutable** — Once a Seq is created, it cannot be
324
- changed, appended to, rearranged or otherwise modified. Instead, any mutative
325
- method called on a Seq will return a new Seq.
408
+ Immutable.js collections are treated as pure data _values_. Two immutable
409
+ collections are considered _value equal_ (via `.equals()` or `is()`) if they
410
+ represent the same collection of values. This differs from JavaScript's typical
411
+ _reference equal_ (via `===` or `==`) for Objects and Arrays which only
412
+ determines if two variables represent references to the same object instance.
326
413
 
327
- **Seq is lazy** Seq does as little work as necessary to respond to any
328
- method call.
414
+ Consider the example below where two identical `Map` instances are not
415
+ _reference equal_ but are _value equal_.
329
416
 
330
- For example, the following does not perform any work, because the resulting
331
- Seq is never used:
417
+ <!-- runkit:activate -->
332
418
 
333
- var oddSquares = Immutable.Seq.of(1,2,3,4,5,6,7,8)
334
- .filter(x => x % 2).map(x => x * x);
335
-
336
- Once the Seq is used, it performs only the work necessary. In this
337
- example, no intermediate arrays are ever created, filter is called three times,
338
- and map is only called once:
419
+ ```js
420
+ // First consider:
421
+ const obj1 = { a: 1, b: 2, c: 3 };
422
+ const obj2 = { a: 1, b: 2, c: 3 };
423
+ obj1 !== obj2; // two different instances are always not equal with ===
424
+
425
+ const { Map, is } = require('immutable');
426
+ const map1 = Map({ a: 1, b: 2, c: 3 });
427
+ const map2 = Map({ a: 1, b: 2, c: 3 });
428
+ map1 !== map2; // two different instances are not reference-equal
429
+ map1.equals(map2); // but are value-equal if they have the same values
430
+ is(map1, map2); // alternatively can use the is() function
431
+ ```
339
432
 
340
- console.log(oddSquares.get(1)); // 9
433
+ Value equality allows Immutable.js collections to be used as keys in Maps or
434
+ values in Sets, and retrieved with different but equivalent collections:
341
435
 
342
- Any collection can be converted to a lazy Seq with `.toSeq()`.
436
+ <!-- runkit:activate -->
343
437
 
344
- var seq = Immutable.Map({a:1, b:1, c:1}).toSeq();
438
+ ```js
439
+ const { Map, Set } = require('immutable');
440
+ const map1 = Map({ a: 1, b: 2, c: 3 });
441
+ const map2 = Map({ a: 1, b: 2, c: 3 });
442
+ const set = Set().add(map1);
443
+ set.has(map2); // true because these are value-equal
444
+ ```
345
445
 
346
- Seq allows for the efficient chaining of sequence operations, especially when
347
- converting to a different concrete type (such as to a JS object):
446
+ Note: `is()` uses the same measure of equality as [Object.is][] for scalar
447
+ strings and numbers, but uses value equality for Immutable collections,
448
+ determining if both are immutable and all keys and values are equal
449
+ using the same measure of equality.
348
450
 
349
- seq.flip().map(key => key.toUpperCase()).flip().toObject();
350
- // { A: 1, B: 1, C: 1 }
451
+ [object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
351
452
 
352
- As well as expressing logic that would otherwise seem memory-limited:
453
+ #### Performance tradeoffs
353
454
 
354
- Immutable.Range(1, Infinity)
355
- .skip(1000)
356
- .map(n => -n)
357
- .filter(n => n % 2 === 0)
358
- .take(2)
359
- .reduce((r, n) => r * n, 1);
360
- // 1006008
455
+ While value equality is useful in many circumstances, it has different
456
+ performance characteristics than reference equality. Understanding these
457
+ tradeoffs may help you decide which to use in each case, especially when used
458
+ to memoize some operation.
361
459
 
362
- Note: An iterable is always iterated in the same order, however that order may
363
- not always be well defined, as is the case for the `Map`.
460
+ When comparing two collections, value equality may require considering every
461
+ item in each collection, on an `O(N)` time complexity. For large collections of
462
+ values, this could become a costly operation. Though if the two are not equal
463
+ and hardly similar, the inequality is determined very quickly. In contrast, when
464
+ comparing two collections with reference equality, only the initial references
465
+ to memory need to be compared which is not based on the size of the collections,
466
+ which has an `O(1)` time complexity. Checking reference equality is always very
467
+ fast, however just because two collections are not reference-equal does not rule
468
+ out the possibility that they may be value-equal.
364
469
 
470
+ #### Return self on no-op optimization
365
471
 
366
- Equality treats Collections as Data
367
- -----------------------------------
472
+ When possible, Immutable.js avoids creating new objects for updates where no
473
+ change in _value_ occurred, to allow for efficient _reference equality_ checking
474
+ to quickly determine if no change occurred.
368
475
 
369
- `Immutable` provides equality which treats immutable data structures as pure
370
- data, performing a deep equality check if necessary.
476
+ <!-- runkit:activate -->
371
477
 
372
- ```javascript
373
- var map1 = Immutable.Map({a:1, b:1, c:1});
374
- var map2 = Immutable.Map({a:1, b:1, c:1});
375
- assert(map1 !== map2); // two different instances
376
- assert(Immutable.is(map1, map2)); // have equivalent values
377
- assert(map1.equals(map2)); // alternatively use the equals method
478
+ ```js
479
+ const { Map } = require('immutable');
480
+ const originalMap = Map({ a: 1, b: 2, c: 3 });
481
+ const updatedMap = originalMap.set('b', 2);
482
+ updatedMap === originalMap; // No-op .set() returned the original reference.
378
483
  ```
379
484
 
380
- `Immutable.is()` uses the same measure of equality as [Object.is][]
381
- including if both are immutable and all keys and values are equal
382
- using the same measure of equality.
485
+ However updates which do result in a change will return a new reference. Each
486
+ of these operations occur independently, so two similar updates will not return
487
+ the same reference:
383
488
 
384
- [Object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
489
+ <!-- runkit:activate -->
385
490
 
491
+ ```js
492
+ const { Map } = require('immutable');
493
+ const originalMap = Map({ a: 1, b: 2, c: 3 });
494
+ const updatedMap = originalMap.set('b', 1000);
495
+ // New instance, leaving the original immutable.
496
+ updatedMap !== originalMap;
497
+ const anotherUpdatedMap = originalMap.set('b', 1000);
498
+ // Despite both the results of the same operation, each created a new reference.
499
+ anotherUpdatedMap !== updatedMap;
500
+ // However the two are value equal.
501
+ anotherUpdatedMap.equals(updatedMap);
502
+ ```
386
503
 
387
- Batching Mutations
388
- ------------------
504
+ ## Batching Mutations
389
505
 
390
506
  > If a tree falls in the woods, does it make a sound?
391
507
  >
@@ -396,68 +512,139 @@ Batching Mutations
396
512
 
397
513
  Applying a mutation to create a new immutable object results in some overhead,
398
514
  which can add up to a minor performance penalty. If you need to apply a series
399
- of mutations locally before returning, `Immutable` gives you the ability to
515
+ of mutations locally before returning, Immutable.js gives you the ability to
400
516
  create a temporary mutable (transient) copy of a collection and apply a batch of
401
517
  mutations in a performant manner by using `withMutations`. In fact, this is
402
- exactly how `Immutable` applies complex mutations itself.
518
+ exactly how Immutable.js applies complex mutations itself.
403
519
 
404
520
  As an example, building `list2` results in the creation of 1, not 3, new
405
521
  immutable Lists.
406
522
 
407
- ```javascript
408
- var list1 = Immutable.List.of(1,2,3);
409
- var list2 = list1.withMutations(function (list) {
523
+ <!-- runkit:activate -->
524
+
525
+ ```js
526
+ const { List } = require('immutable');
527
+ const list1 = List([1, 2, 3]);
528
+ const list2 = list1.withMutations(function (list) {
410
529
  list.push(4).push(5).push(6);
411
530
  });
412
- assert(list1.size === 3);
413
- assert(list2.size === 6);
531
+ assert.equal(list1.size, 3);
532
+ assert.equal(list2.size, 6);
414
533
  ```
415
534
 
416
- Note: `immutable` also provides `asMutable` and `asImmutable`, but only
535
+ Note: Immutable.js also provides `asMutable` and `asImmutable`, but only
417
536
  encourages their use when `withMutations` will not suffice. Use caution to not
418
537
  return a mutable copy, which could result in undesired behavior.
419
538
 
420
- *Important!*: Only a select few methods can be used in `withMutations` including
539
+ _Important!_: Only a select few methods can be used in `withMutations` including
421
540
  `set`, `push` and `pop`. These methods can be applied directly against a
422
541
  persistent data-structure where other methods like `map`, `filter`, `sort`,
423
542
  and `splice` will always return new immutable data-structures and never mutate
424
543
  a mutable collection.
425
544
 
545
+ ## Lazy Seq
426
546
 
427
- Documentation
428
- -------------
547
+ `Seq` describes a lazy operation, allowing them to efficiently chain
548
+ use of all the higher-order collection methods (such as `map` and `filter`)
549
+ by not creating intermediate collections.
429
550
 
430
- [Read the docs](http://facebook.github.io/immutable-js/docs/) and eat your vegetables.
551
+ **Seq is immutable** Once a Seq is created, it cannot be
552
+ changed, appended to, rearranged or otherwise modified. Instead, any mutative
553
+ method called on a `Seq` will return a new `Seq`.
431
554
 
432
- Docs are automatically generated from [Immutable.d.ts](https://github.com/facebook/immutable-js/blob/master/type-definitions/Immutable.d.ts).
433
- Please contribute!
555
+ **Seq is lazy** `Seq` does as little work as necessary to respond to any
556
+ method call. Values are often created during iteration, including implicit
557
+ iteration when reducing or converting to a concrete data structure such as
558
+ a `List` or JavaScript `Array`.
434
559
 
435
- Also, don't miss the [Wiki](https://github.com/facebook/immutable-js/wiki) which
436
- contains articles on specific topics. Can't find something? Open an [issue](https://github.com/facebook/immutable-js/issues).
560
+ For example, the following performs no work, because the resulting
561
+ `Seq`'s values are never iterated:
437
562
 
563
+ ```js
564
+ const { Seq } = require('immutable');
565
+ const oddSquares = Seq([1, 2, 3, 4, 5, 6, 7, 8])
566
+ .filter(x => x % 2 !== 0)
567
+ .map(x => x * x);
568
+ ```
569
+
570
+ Once the `Seq` is used, it performs only the work necessary. In this
571
+ example, no intermediate arrays are ever created, filter is called three
572
+ times, and map is only called once:
573
+
574
+ ```js
575
+ oddSquares.get(1); // 9
576
+ ```
577
+
578
+ Any collection can be converted to a lazy Seq with `Seq()`.
438
579
 
439
- Testing
440
- -------
580
+ <!-- runkit:activate -->
441
581
 
442
- If you are using the [Chai Assertion Library](http://chaijs.com/), [Chai Immutable](https://github.com/astorije/chai-immutable) provides a set of assertions to use against `Immutable` collections.
582
+ ```js
583
+ const { Map, Seq } = require('immutable');
584
+ const map = Map({ a: 1, b: 2, c: 3 });
585
+ const lazySeq = Seq(map);
586
+ ```
443
587
 
588
+ `Seq` allows for the efficient chaining of operations, allowing for the
589
+ expression of logic that can otherwise be very tedious:
444
590
 
445
- Contribution
446
- ------------
591
+ ```js
592
+ lazySeq
593
+ .flip()
594
+ .map(key => key.toUpperCase())
595
+ .flip();
596
+ // Seq { A: 1, B: 2, C: 3 }
597
+ ```
447
598
 
448
- Use [Github issues](https://github.com/facebook/immutable-js/issues) for requests.
599
+ As well as expressing logic that would otherwise seem memory or time
600
+ limited, for example `Range` is a special kind of Lazy sequence.
449
601
 
450
- We actively welcome pull requests, learn how to [contribute](./CONTRIBUTING.md).
602
+ <!-- runkit:activate -->
451
603
 
604
+ ```js
605
+ const { Range } = require('immutable');
606
+ Range(1, Infinity)
607
+ .skip(1000)
608
+ .map(n => -n)
609
+ .filter(n => n % 2 === 0)
610
+ .take(2)
611
+ .reduce((r, n) => r * n, 1);
612
+ // 1006008
613
+ ```
452
614
 
453
- Changelog
454
- ---------
615
+ ## Documentation
455
616
 
456
- Changes are tracked as [Github releases](https://github.com/facebook/immutable-js/releases).
617
+ ## Documentation
457
618
 
619
+ [Read the docs](https://immutable-js.com) and eat your vegetables.
458
620
 
459
- Thanks
460
- ------
621
+ Docs are automatically generated from [Immutable.d.ts](https://github.com/immutable-js/immutable-js/blob/main/type-definitions/Immutable.d.ts).
622
+ Please contribute!
623
+
624
+ Also, don't miss the [Wiki](https://github.com/immutable-js/immutable-js/wiki) which
625
+ contains articles on specific topics. Can't find something? Open an [issue](https://github.com/immutable-js/immutable-js/issues).
626
+
627
+ ## Testing
628
+
629
+ If you are using the [Chai Assertion Library](https://chaijs.com/), [Chai Immutable](https://github.com/astorije/chai-immutable) provides a set of assertions to use against Immutable.js collections.
630
+
631
+ ## Contribution
632
+
633
+ ## Contribution
634
+
635
+ Use [Github issues](https://github.com/immutable-js/immutable-js/issues) for requests.
636
+
637
+ We actively welcome pull requests, learn how to [contribute](https://github.com/immutable-js/immutable-js/blob/main/.github/CONTRIBUTING.md).
638
+
639
+ Immutable.js is maintained within the [Contributor Covenant's Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/).
640
+
641
+ We actively welcome pull requests, learn how to [contribute](https://github.com/immutable-js/immutable-js/blob/main/.github/CONTRIBUTING.md).
642
+
643
+ ## Changelog
644
+
645
+ Changes are tracked as [Github releases](https://github.com/immutable-js/immutable-js/releases).
646
+
647
+ ## Thanks
461
648
 
462
649
  [Phil Bagwell](https://www.youtube.com/watch?v=K2NYwP90bNs), for his inspiration
463
650
  and research in persistent data structures.
@@ -465,8 +652,6 @@ and research in persistent data structures.
465
652
  [Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package
466
653
  name. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).
467
654
 
655
+ ## License
468
656
 
469
- License
470
- -------
471
-
472
- `Immutable` is [BSD-licensed](https://github.com/facebook/immutable-js/blob/master/LICENSE). We also provide an additional [patent grant](https://github.com/facebook/immutable-js/blob/master/PATENTS).
657
+ Immutable.js is [MIT-licensed](./LICENSE).