Skip to content

Instantly share code, notes, and snippets.

@Garciat
Last active June 10, 2016 12:05
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 Garciat/07d74ba686ce04eccb11faa44f2ae229 to your computer and use it in GitHub Desktop.
Save Garciat/07d74ba686ce04eccb11faa44f2ae229 to your computer and use it in GitHub Desktop.
/* Lazy */
class Memoized {
constructor(it) {
this.it = it;
this.done = false;
this.mem = [];
}
[Symbol.iterator]() {
return new MemoizedIterator(this);
}
}
class MemoizedIterator {
constructor(m) {
this.m = m;
this.i = 0;
}
next() {
if (this.i < this.m.mem.length) {
return { value: this.m.mem[this.i++], done: false };
}
if (this.m.done) {
return { value: undefined, done: true };
}
const res = this.m.it.next();
if (res.done) {
this.m.done = true;
return { value: undefined, done: true };
}
const val = res.value;
this.m.mem[this.i] = val;
this.i += 1;
return { value: val, done: false };
}
}
function memoized(f) {
return new Chain(new Memoized(f()));
}
/* Iterator */
function* map(xs, f) {
for (let x of xs) {
yield f(x);
}
}
function* flatMap(xs, f) {
for (let x of xs) {
yield* f(x);
}
}
function forEach(xs, f) {
for (let x of xs) {
f(x);
}
}
function* take(xs, n) {
let i = 0;
for (let x of xs) {
if (i >= n) {
break;
}
yield x;
i += 1;
}
}
function* cycle(xs) {
while (true) {
yield* xs;
}
}
function* pairwise(xs) {
const sentinel = {};
let last = sentinel;
for (let x of xs) {
if (last !== sentinel) {
yield [last, x];
}
last = x;
}
}
function* takeWhile(xs, f) {
for (let x of xs) {
if (!f(x)) {
break;
}
yield x;
}
}
function* concat(xs, ys) {
yield* xs;
yield* ys;
}
function* zipWith(xs, ys, f) {
const itx = xs[Symbol.iterator]();
const ity = ys[Symbol.iterator]();
while (true) {
const rx = itx.next();
const ry = ity.next();
if (rx.done || ry.done) {
return;
}
const x = rx.value;
const y = ry.value;
yield f(x, y);
}
}
function* tail(xs) {
const itx = xs[Symbol.iterator]();
let rx = itx.next();
if (rx.done) {
return;
}
while (true) {
const rx = itx.next();
if (rx.done) {
return;
}
yield rx.value;
}
}
function zip(xs, ys) {
return zipWith(xs, ys, (x, y) => [x, y]);
}
function reduce(xs, o, f) {
let s = o;
for (let x of xs) {
s = f(s, x);
}
return s;
}
function* filter(xs, f) {
for (let x of xs) {
if (f(x)) {
yield x;
}
}
}
/* Chaining */
class Chain {
constructor(xs) {
this.xs = xs;
}
[Symbol.iterator]() {
return this.xs[Symbol.iterator]();
}
forEach(f) {
return forEach(this.xs, f);
}
reduce(o, f) {
return reduce(this.xs, o, f);
}
toArray() {
return Array.from(this.xs);
}
}
const CHAIN_OPERATORS = [
map, flatMap, take, cycle, pairwise, takeWhile, concat, zipWith, tail, zip, filter
];
for (let op of CHAIN_OPERATORS) {
Chain.prototype[op.name] = function (...args) {
args.unshift(this);
return new Chain(op.apply(undefined, args));
};
}
function chain(xs) {
return new Chain(xs);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment