iter-tools-es
Version:
The iterable toolbox
151 lines (123 loc) • 3.27 kB
JavaScript
const {
isIterable
} = require('../impls/is-iterable/is-iterable.js');
const {
isLoopable
} = require('../impls/is-loopable/is-loopable.js');
const {
isWrappable
} = require('../impls/is-wrappable/is-wrappable.js');
const {
nullableWrap: wrap
} = require('./wrap.js');
const {
variadicCurryWithValidation
} = require('./curry.js');
const {
_,
__iterate
} = require('./symbols.js');
exports.wrap = wrap;
exports.isIterable = isIterable;
exports.isLoopable = isLoopable;
exports.isWrappable = isWrappable;
function ensureIterable(value) {
if (!isWrappable(value)) {
if (typeof value.next === 'function') {
throw new TypeError('iter-tools received a value that looked like an iterator but was not iterable. Get help fixing this: https://github.com/iter-tools/iter-tools/wiki/Making-iterators-iterable');
} else throw new TypeError('Expected an iterable, null, or undefined');
} else if (isIterable(value)) {
return value;
} else {
return wrap(value);
}
}
exports.ensureIterable = ensureIterable;
function callReturn(iterator) {
if ('return' in iterator) iterator.return();
}
exports.callReturn = callReturn;
function BaseIterableIterator(fn, args) {
this[_] = {
fn,
args,
staticIterator: null
};
}
exports.BaseIterableIterator = BaseIterableIterator;
Object.assign(BaseIterableIterator.prototype, {
constructor: BaseIterableIterator,
[__iterate]() {
const {
fn,
args
} = this[_];
return fn(...args);
},
next() {
const this_ = this[_];
this_.staticIterator = this_.staticIterator || this[__iterate]();
return this_.staticIterator.next();
},
return(value) {
const this_ = this[_];
this_.staticIterator = this_.staticIterator || this[__iterate]();
return this_.staticIterator.return(value);
},
throw(error) {
const this_ = this[_];
this_.staticIterator = this_.staticIterator || this[__iterate]();
return this_.staticIterator.throw(error);
}
});
function IterableIterator(...args) {
BaseIterableIterator.apply(this, args);
}
exports.IterableIterator = IterableIterator;
IterableIterator.prototype = Object.assign(Object.create(BaseIterableIterator.prototype), {
constructor: IterableIterator,
[Symbol.iterator]() {
return this[__iterate]();
}
});
function makeFunctionConfig(fn, fnConfig = {}) {
const {
validateArgs = _ => {},
variadic = false,
reduces = false,
growRight = false,
minArgs = fn.length - 1,
maxArgs = fn.length - 1,
applyOnIterableArgs = ensureIterable
} = fnConfig;
return {
fn,
validateArgs,
variadic,
reduces,
growRight,
minArgs,
maxArgs,
isIterable: isWrappable,
iterableType: 'iterable',
applyOnIterableArgs,
IterableClass: IterableIterator
};
}
function cache(it) {
return [...it];
}
exports.cache = cache;
function wrapWithIterableIterator(fn, {
validateArgs = _ => _
} = {}) {
return (...args) => {
validateArgs(args);
return new IterableIterator(fn, args);
};
}
exports.wrapWithIterableIterator = wrapWithIterableIterator;
const iterableCurry = (fn, config) => {
return variadicCurryWithValidation(makeFunctionConfig(fn, config));
};
exports.iterableCurry = iterableCurry;