immutable 4.0.0-rc.9 → 4.0.0

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