Created
February 15, 2019 07:34
-
-
Save andrewgreenh/d94a1fe9094986b388c363ae6192b536 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Live Coding: Iterables and why you should care | |
// This object implements the iterable interface. | |
// It has a function in the property [Symbol.iterator] that returns an iterator | |
let iterable = { | |
[Symbol.iterator]: () => { | |
// The iterator is an object that has a function in the property next that returns an interator result | |
let iterator = { | |
next: () => { | |
// The iterator result is an object with the two properties value and done | |
let iteratorResult = { | |
value: 1, | |
done: false | |
}; | |
return iteratorResult; | |
} | |
}; | |
return iterator; | |
} | |
}; | |
// Generator functions can greatly simplify the creation of iterables and iterators | |
// When called, a stateful iterable iterator is beeing returned. | |
function* sequence(start = 0, end = Infinity, step = 1) { | |
let next = start; | |
while (next < end) { | |
// The yield keyword produces the next value of the iterator. | |
// After this, the function execution is stopped until .next() is called on the iterator again. | |
yield next; | |
next += step; | |
} | |
} | |
// Transforming every value of the iterable with a given transform function | |
function* map(iterable, transform) { | |
for (let item of iterable) { | |
yield transform(item); | |
} | |
} | |
// Transforming every value of the iterable into multiple values with a given transform function | |
function* flatMap(iterable, transform) { | |
for (let item of iterable) { | |
yield* transform(item); | |
} | |
} | |
// Only keep values that produce a truthy value with the given condition function | |
function* filter(iterable, condition) { | |
for (let item of iterable) { | |
if (condition(item)) yield item; | |
} | |
} | |
// Create data pipelines to declaratively transform the initial value in multiple steps | |
function pipe(initialValue) { | |
return function through(...transforms) { | |
let last = initialValue; | |
for (let transform of transforms) { | |
last = transform(last); | |
} | |
return last; | |
}; | |
} | |
// Only pull the first n values from the iterable and close the iterator (with the break keyword) | |
function* take(iterable, n) { | |
let i = 0; | |
for (let item of iterable) { | |
if (i >= n) break; | |
yield item; | |
i++; | |
} | |
} | |
// Example pipeline: | |
// 1. create a new Set with the values 0, 1, 2 | |
// 2. Duplicate each value with flatMap: 0, 0, 1, 1, 2, 2 | |
// 3. Drop all odd numbers: 0, 0, 2, 2 | |
// 4. Increment each value by 100: 100, 100, 102, 102 | |
for (let i of pipe(new Set([0, 1, 2]))( | |
_ => flatMap(_, i => [i, i]), | |
_ => filter(_, i => i % 2 === 0), | |
_ => map(_, i => i + 100) | |
)) { | |
console.log(i); | |
} | |
// Resources: | |
// Spec: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment