'use strict'; function identity(x) { return x; } export class Iterator { constructor(from) { let next; if (Symbol.iterator in from.__proto__) { const iter = from.__proto__[Symbol.iterator].call(from); next = iter.next.bind(iter); } else if (typeof from === 'function') { next = from; } else { throw new TypeError('Iterator class needs iterable input'); } Object.defineProperty(this, 'next', { value: next, writable: false, enumerable: true, configurable: false, }); } [Symbol.iterator]() { return this; } map(f) { const next = this.next; return new Iterator(function() { const y = next(); if (y.done) { return y; } else { return { value: f(y.value), done: false }; } }); } filter(f) { const next = this.next; return new Iterator(function() { let y; while (!(y = next()).done && !f(y.value)) { continue; } return y; }); } take(limit) { let remaining = Number(limit) & -1; const next = this.next; return new Iterator(function() { if (remaining > 0) { remaining -= 1; return next(); } else { return { value: undefined, done: true }; } }); } drop(limit) { let remaining = Number(limit) & -1; const next = this.next; return new Iterator(function() { while (remaining > 0 && !next().done) { remaining -= 1; } return next(); }); } asIndexedPairs() { const next = this.next; let index = 0; return new Iterator(function() { const y = next(); if (y.done) { return y; } else { return { value: [index++, y.value], done: false }; } }); } flatMap(f) { const next = this.next; let innerNext; return new Iterator(function() { for (;;) { if (innerNext) { let y = innerNext(); if (!y.done) { return y; } } let z = next(); if (z.done) { innerNext = undefined; return z; } const iter = y.value.__proto__[Symbol.iterator].call(y.value); innerNext = iter.next.bind(iter); } }); } reduce(f, state) { if (typeof state === 'undefined') { const first = this.next(); if (first.done) { throw new TypeError('reduce: empty iterator'); } state = first.value; } let y; while (!(y = this.next()).done) { state = f(state, y.value); } return state; } toArray() { return [...this]; } forEach(f) { let y; while (!(y = this.next()).done) { f(y.value); } /* extension: return final value from underlying iterator */ return y.value; } some(f) { /* extension: if f is undefined, assume identity function */ if (typeof f === 'undefined') { f = identity; } let y; while (!(y = this.next()).done) { if (f(y.value)) { return true; } } return false; } every(f) { /* extension: if f is undefined, assume identity function */ if (typeof f === 'undefined') { f = identity; } let y; while (!(y = this.next()).done) { if (!f(y.value)) { return false; } } return true; } find(f) { /* extension: if f is undefined, return the first 'truthy' value */ if (typeof f === undefined) { f = identity; } let y; while (!(y = this.next()).done) { if (f(y.value)) { return y.value; } } } /* extension */ includes(x) { return this.some(function matches(y) { return y == x; }); } /* extension */ strictlyIncludes(x) { return this.some(function matches(y) { return y === x; }); } }; export default Iterator;