time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

README.md (28923B)


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