Skip to content

Instantly share code, notes, and snippets.

@andrewgreenh
Created February 15, 2019 07:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewgreenh/d94a1fe9094986b388c363ae6192b536 to your computer and use it in GitHub Desktop.
Save andrewgreenh/d94a1fe9094986b388c363ae6192b536 to your computer and use it in GitHub Desktop.
// 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