immutable
Effecient immutable collections in javascript.
Why?
Using immutable objects can make code easier to reason about, by eliminating a class of difficult-to-find side-effects that can (and do) trip programmers up.
Install
npm install immutable
Usage
Immutable has two types of collection: objects and arrays. Like regular JavaScript Objects and Arrays, both act as key:value stores (using strings as the keys).
Basic Manipulation
creation
var person = im.object({ name: 'joe bloggs', age: 34 })
var numbers = im.array([1, 2, 3, 4, 5])
.assoc
var emptyObj = im.object()
var person = emptyObj.assoc({ name: 'joe bloggs', age: 34 })
var personWithSports = o.assoc('sport', 'golf')
var emptyArr = im.array()
var numbers = emptyArr.assoc([1, 2, 3, 4, 5])
var upTo6 = emptyArr.assoc(5, 6)
.get
var person = im.object({ name: 'joe bloggs', age: 34 })
person.get('age')
var numbers = im.array([1, 2, 3, 4, 5])
numbers.get(0)
.has
var person = im.object({ name: 'joe bloggs', age: 34 })
person.has('name')
person.has('discography')
.dissoc
Create a collection like this one, but without a particular property:
var person = im.object({ name: 'joe bloggs', age: 34 })
var personShyAboutAge = person.dissoc('age')
personShyAboutAge.has('age')
var numbers = im.array([1, 2, 3, 4, 5])
var upTo4 = numbers.dissoc(4)
numbers.has(4)
.mutable / .toJSON
Create a regular JavaScript object from an immutable one:
var person = im.object({ name: 'joe bloggs', age: 34 })
person.mutable()
The .toJSON
alias allows immutable objects to be serialised seamlessly with regular objects:
var favouritePeople = {
joe: im.object({ name: 'joe bloggs', age: 34, sports: im.array(['golf', 'carting']) })
}
var data = JSON.stringify(favouritePeople)
data // = '{ "joe": { "name": "joe bloggs", "age": 34, "sports": ["golf", "carting"] } }'
.immutable
.immutable
is a simple boolean flag, which is set to true
on all immutable objects, for easy, consistent querying:
im.object().immutable
im.array().immutable
Value Equality
Collections can be checked for equality:
var person1 = im.object({ name: 'joe bloggs', age: 34 })
var person2 = im.object({ name: 'joe bloggs', age: 34 })
var person3 = im.object({ name: 'joe bloggs', age: 34, sport: 'golf' })
person1.equal(person2)
person3.equal(person2)
Collections are considered equal when:
- They are immutable
- They have all the same keys
- All values are strict equal, or .equal to one another
Iteration
Immutable objects and arrays can be iterated over almost identically, except that:
- objects iterate over all keys, and return objects where appropriate;
- arrays iterate over only numberic keys, and return arrays where appropriate.
All iterator functions (unless mentioned) well pass the value, the key, and the original immutable object to their callback functions.
.map
var inc = function(a){ return a + 1 }
var coordinates = im.object({ x: 1, y: 1 })
coordinates.map(inc).mutable()
var numbers = im.array([1, 2, 3, 4, 5])
numbers.map(inc).mutable()
.forEach
var log = console.log.bind(console)
var person = im.object({ name: 'joe bloggs', age: 34 })
person.map(log)
.filter
var isNum = function(a){ return typeof a === 'number' }
var person = im.object({ name: 'joe bloggs', age: 34 })
person.filter(isNum).mutable()
var alphaNumber = im.array(['a', 1, 'b', 2, 'c', 3])
alphaNumber.filter(isNum).mutable()
.every
var isNum = function(a){ return typeof a === 'number' }
var person = im.object({ name: 'joe bloggs', age: 34 })
person.every(isNum)
var alphaNumber = im.array(['a', 1, 'b', 2, 'c', 3])
alphaNumber.every(isNum)
.some
var isNum = function(a){ return typeof a === 'number' }
var person = im.object({ name: 'joe bloggs', age: 34 })
person.some(isNum)
var alphaNumber = im.array(['a', 1, 'b', 2, 'c', 3])
alphaNumber.some(isNum)
.reduce
var flip = function(coll, val, key){
return coll.assoc(key, val)
}
var person = im.object({ x: '1', y: '2', z: '3' })
var flippedPerson = person.reduce(flip, im.object())
flippedPerson.mutable()
var cat = function(a, b){ return a + b }
var letters = im.array(['a', 'b', 'c'])
letters.reduce(cat)
.reduceRight
array only
var cat = function(a, b){ return a + b }
var letters = im.array(['a', 'b', 'c'])
letters.reduceRight(cat)