On Github killtheliterate / bwdid-iterables
Or: So you want to be a wizard.
Garrett Dawson
@killtheliterate
I've been a front-end dev of 5 years. I work at VictorOps
I love JavaScript
what are iterables, and what do you do with them?
// loopable const theIterable = [1,2,3] // the loop theIterable.forEach(el => console.log(el)) // 1, 2, 3Given these commonalities, TC39 identifies Iterable/Iterator They capture the essence of looping into types
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) }Looks similar to for-in access member directly
// 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)Looks alot like [].map() The arguments object can be passed to an iterator
// 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']Also looks alot like [].map() Composable with ...spread to collect the rest Notably, objects can be destructured, but that's outside this scope
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',' '...]Since they are iterable, they are consumable by iterators
// 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']
// 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]
// 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]...]
// 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}yield keyword exits the function execution resumes where the yield left off
// 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]It's notable that using spread transforms the values into normal stuff
// 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}We can push values into Generators If we assign the last yield to a variable, that variable becomes whatever we push with next()
{ }.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 "how do i loop?" this is why a generator is both iterable and iterator...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]quick aside about linked lists why are they useful? memory and known size collection types in FP are usually linked lists you walk them recursively
[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. when you define a constructor, give it this property...still a linked list
http://bit.ly/1T0WhvJ
// give our type an iteration protocol const iterable = LinkedList()[Symbol.iterator] = () => // etcwe can make a linked list type that describes how it should be walked this makes our type "iterable"
possible infinity
http://bit.ly/1PXumgX
* Event stream * Websockets * Observables * Combinatorsmap, filter and reduce
go broncos