Or: So you want to be a wizard.
Garrett Dawson
@killtheliterate
// loopable
const theIterable = [1,2,3]
// the loop
theIterable.forEach(el => console.log(el)) // 1, 2, 3
Builtin Iterators
// an iterable
const theIterable = 'a string is a list of characters'
// an iterator
// access the member directly
// instead of by index
for(let char of theIterable) {
console.log(char)
}
// an iterable
const theIterable = ['an', 'array', 'is', 'iterable']
// an iterator
const newArray = [...theIterable]
// arguments is iterable
const fn = (...args) => { args.forEach(el => console.log(el)) }
fn(1, 2, 3)
// an iterable
const theCollection = ['hello', 'humans', 'in', 'this', 'room']
// an iterator
let [these, are, pieces, ...iterable] = theCollection
console.log(these) // 'hello'
console.log(iterable) // ['this', 'room']
Builtin Iterables
// an iterable
const theIterable = 'this is iterable'
// an iterator
for(let char of theIterable) {
console.log(char) // each char
}
// an iterator
const chars = [...theIterable]
console.log(chars) // ['t','h','i','s',' '...]
// an iterable
const theIterable = ['this', 'is', 'iterable']
// an iterator
for(let words of theIterable) {
console.log(words) // 'this' 'is'...
}
// an iterator
const sentence = [...theIterable]
console.log(sentence) // ['this', 'is', 'iterable']
The Set object lets you store unique values of any type, whether primitive values or object references.
// an iterable
const theIterable = new Set()
theIterable.add(1)
theIterable.add(3)
theIterable.add(2)
theIterable.add(2)
// an iterator
for(let num of theIterable) {
console.log(num) // 1, 3, 2
}
// an iterator
const numbers = [...theIterable]
console.log(numbers) // [1,3,2]
The Map object is a simple key/value map. Any value (both objects and primitive values) may be used as either a key or a value.
// an iterable
const theIterable = new Map()
theIterable.set('one', 1)
theIterable.set('three', 3)
theIterable.set('two', 2)
// an iterator
for(let numTuple of theIterable) {
console.log(numTuple) // ['one', 1]...
}
// an iterator
const tuples = [...theIterable]
console.log(tuples) // [['one', 1]...]
Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.
// an iterable
const maker = function* () {
yield 1
yield 2
yield 3
}
const theIterable = maker() // this gives us back a generator object
const first = theIterable.next() // which we can step through
console.log(first) // {value: 1, done: false}
// an iterable
const maker = function* () {
let index = 0 // the mutated state will be persisted
while(index < 3) {
yield index++
}
}
const theIterable = maker() // this gives us back a generator object
// which we can operate on with an iterator
// this works because the generator is finite
const nums = [...theIterable] // [0,1,2]
// pushing a value with next() will become the result of the last
// yield. like this:
const maker = function* () {
let first = yield
let second = yield first
let third = yield second
yield
}
const echo = maker()
console.log(echo.next(1))// {value: null, done: false}
console.log(echo.next(500)) // {value: 500, done: false}
console.log(echo.next('sup')) // {value: 'sup', done: false}
{ }.next()
An object is an iterator when it knows how to access items from a collection one at a time, while keeping track of its current position within that sequence
...for a linked list
http://bit.ly/1I8TKzc
// this is what a linked list looks like
{val: 1, rest: {val: 2, rest: {val: 3, rest: {val: 4, rest: null}}}}
// basically an array
[1, 2, 3, 4]
[Symbol.iterator]
The iterable protocol allows JavaScript objects to define or customize their iteration behavior, such as what values are looped over in a for..of construct.
...still a linked list
http://bit.ly/1T0WhvJ
// give our type an iteration protocol
const iterable = LinkedList()[Symbol.iterator] = () => // etc
possible infinity
http://bit.ly/1PXumgX
map, filter and reduce
go broncos