;(function() {
'use strict';
/** Do basic error checking */
const ARGS_CHECK = true;
/** Expose internal modules for testing */
const EXPOSE_INTERNAL = true;
/** check `Symbol`'s are supported */
if (typeof Symbol === `undefined`) {
throw new Error('es6 Symbols are required for the itbl libary');
}
/** Detect free variable `global` from Node.js. */
const freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
/** Detect free variable `self`. */
const freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Detect free variable `exports`. */
const freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
const freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
/** Used as a reference to the global object. */
const root = freeGlobal || freeSelf || Function('return this')();
/** Used to restore the original `itbl` reference in `itbl.noConflict`. */
const oldItbl = root.itbl;
/** Used to access `[Symbol.iterator]` method */
const iteratorSymbol = Symbol.iterator;
/**
* Function that returns the first argument it recieves
*
* @private
* @memberof itbl
* @since 2.0.0
*
* @param {*} value Any Value.
*
* @returns {boolean} Returns `value`
* @noexcept
*/
const identity = value => value;
/**
* Used to bind `this` and arguments to funciton
*
*/
const funcBind = Function.prototype.bind;
/**
* Determine if a value is a function.
*
* @see http://stackoverflow.com/a/17108198
*
* @private
*
* @param {*} value Value to check if function.
*
* @returns {boolean} Weather value is function or not.
* @noexcept
*/
const _isFunction = value => typeof value === 'function';
/**
* @namespace itbl
*/
/**
* @memberof itbl
* @typedef {{ value: *, done: boolean }} Step
*/
/**
* Base class with prototype containing chained itbl methods.
* This class is returned by `itbl()` and `itbl.wrap()`.
*
* @implements Iterable
* @static
* @memberof itbl
* @since 0.1.0
* @constructor
* @noexcept
*
*/
class _Wrapper {
/**
* Create a new Wrapped iterable/iterator.
*
* @constructor
*
* @since 0.1.0
*
* @param {Object} [options = {}]
* @param {function} [options.next] Method which gets next value of iterator.
* @param {function} [options.throw] Method which resumes the execution of a generator by throwing an error into it and returns an
* object with two properties done and value.
* @param {function} [options.return] Method which returns given value and finishes the iterator.
* @param {function} [options.[Symbol.iterator]] Method which gets iterator to an iterable.
*
*/
constructor({ [iteratorSymbol]: iterMethod, next, throw: thw, return: rtn } = {}) {
// override default [Symbol.iterator] method
if (iterMethod != null) {
this[iteratorSymbol] = iterMethod;
}
if (next != null) {
this.next = next;
}
if (rtn != null) {
this.return = rtn;
}
if (thw != null) {
this.throw = thw;
}
}
/**
* Get an iterator to the wrapped iterable.
*
* By default returns its self but will be overwritten if a
* [Symbol.iterator] method is passed to the constructor.
*
* @function
* @name itbl._Wrapper#[Symbol.iterator]
*
* @since 2.0.0
* @returns {itbl._Wrapper} Returns a wrapped iterator.
*
* @throws Throws if the wrapped value is an iterator or an iterable whose [Symbol.iterator]
* method throws.
*/
[iteratorSymbol]() {
return this;
}
}
/**
* Get the next value of this iterator.
*
* ** This method is only defined if the wrapped value is an iterator. **
*
* @function
* @name itbl._Wrapper#next
* @since 2.0.0
*
* @returns {Step} Returns the next iterator value.
* @throws Throws if the wrapped iterator's next method throws.
*
*/
/**
* Returns given value and finishes the iterator.
*
* ** This method is only defined if the wrapped value is defines a return method **
*
* @function
* @name itbl._Wrapper#return
* @since 2.0.0
*
* @param {*} value The value to return
*
* @returns {Step} Returns a `{@link Step}` with a value of `value`.
* @throws Throws if the wrapped iterator's return method throws.
*
*/
/**
* The throw() method resumes the execution of a generator by throwing an error into it and returns an
* object with two properties done and value.
*
* ** This method is only defined if the wrapped value is an iterator **
*
* @function
* @name itbl._Wrapper#throw
* @since 2.0.0
*
* @param {*} exception The exception to throw. For debugging purposes, it is useful to make it an `instanceof
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error Error}`.
*
* @returns {Step} Returns the next iterator value.
* @throws Throws if the wrapped iterator's return method throws, for a generator function this happens if the
* yield expression is not contained within a try-catch block.
*
*/
/**
* Checks if `value` is an iterator according to es6 iterator protocols.
* An object is an iterator when it implements a next() method. See {@link
* https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols#iterator}
* for more information.
*
* @static
* @memberof itbl
* @since 0.1.0
*
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @noexcept
* @example
*
* function MyIterable() { }
*
* MyIterable.prototype[Symbol.iterator] = function*() {
* while(true) yield 1;
* };
*
* let iterableInstance = new MyIterable();
*
* itbl.isIterator(iterableInstance);
* // => false (this is an iterable but NOT an iterator)
*
* // generator function that is then called
* itbl.isIterator(iterableInstance[Symbol.iterator]());
* // => true (this is both an iterator and also iterable)
*
* itbl.isIterator([1, 2, 3][Symbol.iterator]());
* // => true
*
* for(let i of ['a'])
* itbl.isIterator(i)
* // => false (i is equal to 'a')
*/
const isIterator = value => value != null && _isFunction(value.next);
/**
* Checks if `value` is an iterable object according to es6 iterator protocols.
* In order to be iterable, an object must implement the **@@iterator** method,
* meaning that the object (or one of the objects up its prototype chain)
* must have a property with a `[Symbol.iterator]` key which defines a function.
* (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols#iterable)
*
* @static
* @memberof itbl
* @since 0.1.0
*
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @noexcept
* @example
*
*
* function MyIterable() { }
*
* MyIterable.prototype[Symbol.iterator] = function*(){
* while(true) yield 1;
* }
*
* let iterableInstance = new MyIterable();
*
* itbl.isIterable(iterableInstance);
* // => true
*
* // generator function that is then called
* itbl.isIterable(iterableInstance[Symbol.iterator]());
* // => true (this is both an iterator and also iterable)
*
* itbl.isIterable([1, 2, 3]);
* // => true
*
* itbl.isIterable({1: 1, 2: 2, 3: 3});
* // => false
*/
const isIterable = value => value != null && _isFunction(value[iteratorSymbol]);
/**
* Wraps an iterator, adding chainable itbl methods.
* The `itbl` objects returned by `_wrapIterable()` will conform to both the
* iterable protocol and the iterator protocol as well as defining the `return()`
* and `throw()` methods if (and only if) `iterator` defines them.
*
* Use the methods parameter to overwrite the `next`, `return`, `throw` or
* `[Symbol.iterator]` methods of `iterator`, `this` is bound to `iterator`.
*
* **Note**: There is no error checking.
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
*
* @param {Iterator} iterator Iterator to wrap.
* @param {Object} [methods] Methods to replace in wrapped iterator.
* @param {function} [methods.next] Replacement `next` method.
* @param {function} [methods.return] Replacement `return` method.
* @param {function} [methods.throw] Replacement `throw` method.
* @param {function} [methods.[Symbol.iterator]] Replacement `[Symbol.iterator]` method.
*
* @returns {itbl._Wrapper} Wrapped iterator.
* @noexcept
*
*/
const _wrapIterator = function _wrapIterator(iterator, methods = {}) {
return new _Wrapper(
[iteratorSymbol, 'next', 'return', 'throw']
.map(methodName => [methodName, (methods[methodName] != null ? methods : iterator)[methodName]])
.reduce((obj, [name, method]) => {
obj[name] = method != null ? funcBind.call(method, iterator) : null;
return obj;
}, {})
);
};
/**
* Wraps an iterable, adding chainable itbl methods.
* The `itbl` objects returned by `_wrapIterable()` will conform to the iterable protocol.
*
* The iterator returned by the `[Symbol.iterator]` method will be wrapped and so contain chainable
* itbl methods.
*
* Use the methods parameter to overwrite the `next`, `return`, `throw` or
* `[Symbol.iterator]` methods of the iterator produced by `iterable`.
*
* **Note**: The objects returned by the `[Symbol.iterator]` method are checked to ensure that they are iterators.
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
*
* @param {Iterable} iterable Iterable to wrap.
* @param {object} methods Methods to replace in wrapped iterator.
* @param {function} [methods.next] Replacement `next` method.
* @param {function} [methods.return] Replacement `return` method.
* @param {function} [methods.throw] Replacement `throw` method.
* @param {function} [methods.[Symbol.iterator]] Replacement `[Symbol.iterator]` method.
*
* @returns {itbl._Wrapper} Wrapped iterable.
* @throws Throws `Error` if the objects returned by the `[Symbol.iterator]` method are not iterators.
*
*/
const _wrapIterable = function _wrapIterable(iterable, methods) {
return new _Wrapper({
[iteratorSymbol]() {
let iter = iterable[iteratorSymbol]();
if (ARGS_CHECK && !isIterator(iter)) {
throw new Error('itbl: `[Symbol.iterator]` method has not returned an iterator');
}
return _wrapIterator(iter, methods);
},
});
};
/**
* Wraps a generator function to produce a [wrapped iterable]{@link itbl}.
*
* The generator function can be any function that returns an iterator, this includes functions
* declared `function* gen() {}`.
*
* If the function produces independent iterators each time it is called (which `function*() { ... }` does)
* then iterating over the created iterable wil not cause it to change, so it can be used multiple times.
*
* **Note**: The objects returned by the `generator` are checked to ensure that they are iterators and
* wrapped by in an itbl instance.
*
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
* @param {function} generator A function that returns iterators.
*
* @returns {itbl._Wrapper} An iterable.
* @throws Throws `Error` if the objects returned by the `[Symbol.iterator]` method are not iterators.
*
*/
const _generateIterable = generator => _wrapIterable({ [iteratorSymbol]: generator });
/**
* Gets iterator from `iterable`. This is equivalent to calling `iterable[Symbol.iterator]` but
* produces helpful error messages.
*
* If `iterable` is omitted then an 'empty' iterator is returned.
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
* @param {Iterable} iterable Iterable to get N iterator to.
* @param {String} funcName Name of function to blame error on.
* @param {String} iterableName Name of `iterable` to include in error message;
*
* @returns {itbl._Wrapper} An iterator
* @throws {Error} Throws an error if `iterable` is not iterable.
*
* @example
*
* let it = itbl.getIterator([1,2,3]);
*
* it.next() // { value: 1, done: false }
* it.next() // { value: 2, done: false }
* it.next() // { value: 3, done: false }
* it.next() // { value: undefined, done: true }
*
*/
const _getIterator = function _getIterator(iterable, funcName, iterableName) {
if (ARGS_CHECK && !isIterable(iterable)) {
throw new Error(`\`itbl.${funcName}()\`: ${iterableName} is not iterable as the [Symbol.iterator] method not defined).`);
}
let iterator = iterable[iteratorSymbol]();
if (ARGS_CHECK && !isIterator(iterator)) {
throw new Error(`itbl: ${iterableName} is not iterable as the [Symbol.iterator] method does not return an iterator.`);
}
return _wrapIterator(iterator);
};
/**
* Wraps `value` to produce an object that conforms to the
* iterable protocol and - if `value` is an iterator - the iterator protocol.
*
* If `value` is an iterable or an iterator, then `value` will be wrapped in an
* instance of `itbl`.
*
* If `value` is not an iterable, an iterator or a function then `wrap` will throw
* an exception.
*
* If `value` is a function, an iterable instance of `itbl` will be returned.
* When the `[Symbol.iterator]` method is called, `value` will be invoked.
* - If `value` returns an iterator it will be wrapped
* - If `value` returns an iterable then its
* `[Symbol.iterator]` method will be called and that iterator wrapped.
* - If `value` returns any other value (including a function) an exception
* will be thrown.
*
* Therefore all of these are roughly equivalent:
* ```javascript
* itbl([6]);
* itbl(function() { return [6]; });
* itbl(function() { return [6][Symbol.iterator](); });
*
* // this can only be iterated over once, unlike all the above
* itbl([6][Symbol.iterator]());
* ```
*
* These will raise an exception:
* <!-- skip-example -->
* ```javascript
* itbl(function() { return 6; });
* itbl(6);
* ```
*
* All itbl functions that take an iterable as their first parameter
* and return an iterable are chainable and so can be called as methods of the
* wrapped value.
*
* The chainable methods are:
*
* `filter` and `map`.
*
* @static
* @since 0.1.0
* @param {*} value The value to wrap.
*
* @returns {itbl._Wrapper} An iterable which may also be an iterator.
* @throws If `value` defines a `[Symbol.iterator]` method but that method does not
* return valid iterators then an `Error` will be thrown when the wrapped iterable
* is iterated over.
*
* @example
* let students = [
* {
* name: 'Martin Smith',
* subject: 'Maths',
* },
* {
* name: 'John Arthur',
* subject: 'English',
* },
* {
* name: 'Rachel Richardson',
* subject: 'Maths',
* },
* ];
*
* // get the name of all maths students
* let mathematicians = itbl(students)
* .filter(_.matchesProperty('subject', 'Maths'))
* .map(_.property('name'));
*
* [...mathematicians];
* // -> ['Martin Smith', 'Rachel Richardson']
*
* let arr = [1, 7, 8, 9];
*
* let arrayReverse = function arrayReverse(array) {
* return itbl(function* () {
* let i = array.length-1;
* while(i >= 0) {
* yield array[i];
* i--;
* }
* });
* };
*
* [...arrayReverse(arr)];
* // -> [9, 8, 7, 1]
*
*/
const itbl = function itbl(value) {
if (value instanceof _Wrapper) {
return value;
}
if (isIterator(value)) {
return _wrapIterator(value);
}
// note iterators may also be iterable but they are treated as iterators
if (isIterable(value)) {
return _wrapIterable(value);
}
if (_isFunction(value)) {
return _generateIterable(function() {
let result = value();
if (isIterator(value)) {
return result;
}
// get iterator from iterable
if (isIterable(result)) {
return result[iteratorSymbol]();
}
throw new Error('itbl(): the object returned from value is not an iterable or an iterator');
});
}
throw new Error('itbl(): value is not an iterable, an iterator or a generator function');
};
const wrap = itbl;
itbl.itbl = itbl.wrap = itbl;
itbl.prototype = _Wrapper.prototype;
itbl.prototype.constructor = itbl;
/**
* Creates a new iterable whose iterators will have values corresponding to the value
* of the Iterator of the original iterable run through `iteratee`.
* The iteratee is invoked with only one argument (value).
*
*
* @static
* @memberof itbl
* @since 0.1.0
* @param {Iterable} iterable Iterable to map values of.
* @param {Function} [iteratee = _.identity] Function to run each value though.
*
* @returns {itbl._Wrapper} `iterable` mapped through `iteratee`, if `iterable` was an iterator then
* an iterator is returned, otherwise an iterable is returned.
* @throws {Error} Throws an error if `iterable` is not iterable.
*
* @example
*
* for(let coor of itbl.map([0, 1, 2, 3, 4, 5], x => ({ x, y: Math.exp(x) }))) {
* context.lineTo(coor.x, coor.y);
* }
*
* let mySet = new Set().add(1).add('a').add(NaN);
*
* [...itbl.map(mySet, value => value + 1)];
* // [2, 'a1', NaN]
*
* var users = [
* { 'user': 'barney' },
* { 'user': 'fred' },
* ];
*
* [...itbl.map(users, _.property('user'))];
* // => ['barney', 'fred']
*
*/
const map = function map(iterable, iteratee) {
iteratee = iteratee != null
? iteratee
: identity;
if (ARGS_CHECK && !isIterable(iterable)) {
throw new Error('itbl.map: `iterable` does not define the `[Symbol.iterator]` method');
}
return (isIterator(iterable)
? _wrapIterator
: _wrapIterable
)(iterable, {
next() {
const step = this.next();
let mapped;
if (!step.done) {
mapped = iteratee(step.value);
}
return {
value: mapped,
done: step.done,
};
},
});
};
_Wrapper.prototype.map = function(iteratee) {
return map(this, iteratee);
};
/**
* Creates a new iterable containing values which the `predicate` returns truthy for.
*
*
* @static
* @memberof itbl
* @since 0.1.0
* @param {Iterable} iterable Iterable to filter the values of.
* @param {Function} [predicate = _.identity] Function to run each value though.
*
* @returns {itbl._Wrapper} `iterable` filtered using `predicate`, if `iterable` was an iterator then
* an iterator is returned, otherwise an iterable is returned.
* @throws {Error} Throws an error if iterators are not supported or the `iterable` is not iterable.
*
* @example
*
* [...itbl.filter([0,1,2,3,4,5], val => val%2 === 0)];
* // [0,2,4]
*
* let mySet = new Set().add(1).add('a').add(NaN);
*
* [...itbl.filter(mySet, value => _.isFinite)];
* // [1]
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': true },
* { 'user': 'fred', 'age': 40, 'active': false }
* ];
*
* [...itbl.filter(users, function(o) { return !o.active; })];
* // => objects for ['fred']
*
* [...itbl.filter(users, _.matches({ 'age': 36, 'active': true }))];
* // => objects for ['barney']
*
* [...itbl.filter(users, _.matchesProperty('active', false))];
* // => objects for ['fred']
*
* [...itbl.filter(users, _.property('active'))];
* // => objects for ['barney']
*
*/
const filter = function filter(iterable, predicate) {
predicate = predicate != null
? predicate
: identity;
if (ARGS_CHECK && !isIterable(iterable)) {
throw new Error('itbl.filter: `iterable` does not define the `[Symbol.iterator]` method');
}
return (isIterator(iterable)
? _wrapIterator
: _wrapIterable
)(iterable, {
next() {
let step;
while (!(step = this.next()).done && !predicate(step.value)) {}
return step;
},
});
};
_Wrapper.prototype.filter = function(predicate) {
return filter(this, predicate);
};
/**
* Combines the iterables in `iterable` into a single iterable containing iterables
* of values from each iterable in `iterable`.
*
* ** `iterable` is not checked to see if it is actually an iterable. **
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
* @param {Iterable} iterable Collection of iterators
*
* @returns {itbl._Wrapper} Iterable containing collection of values
* @throws {Error} Throws an error if the values of `iterable` are not iterable.
*
*/
function _iterableCombine(iterable) {
let n = 0;
let iterators = [...itbl.map(iterable, iterableValue =>
_getIterator(iterableValue, 'combine', `${++n}th value of \`collection\``)
)];
let returnValues = [];
return function() {
let values = [],
anyDone = false,
allDone = true,
i = 0;
for (let step of iterators.map(iterator => iterator.next())) {
returnValues[i] = step.done ? step.value : returnValues[i];
values.push(!step.done ? step.value : undefined);
anyDone = anyDone || step.done;
allDone = allDone && step.done;
// TODO don't like having index variable in for-of loop
++i;
}
return { values, returnValues, anyDone, allDone };
};
}
/**
* Combines the iterables in `collection` into a single iterable containing collections
* of values from each iterable in `collection`.
*
* `collection` can either be an Iterable or an object containing Iterables which
* will be combined. The first value in the combined Iterable will be an Iterable or
* an object containing the first values of the Iterables in `collection`, the second
* value containing the second values of the Iterables in `collection` and so on.
*
* The value of `finish` determines when the iteration ends.
*
* * If `finish === 'early' or 'e'` (default) then the iteration ends as soon as the first iterator from
* `collection` ends.
*
* * If `finish === 'late' or 'l'` then the iteration continues untill all iterators from `collection` are done.
* Values corresponding to iterators that have ended are `undefined`.
*
* * If `finish === 'together' or 't'` then all iterators from `collection` must finish on the same iteration or
* else an `Error` is thrown.
*
* **Note**: The return value of the iterator is a collection of the of the return values the iterators
* from `collection`. Return values corresponding to iterators that have not yet ended are `undefined`
*
* `combine` is particularly powerful when used with
* [es6 destructuring assignment](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment).
*
* @static
* @memberof itbl
* @since 0.1.0
* @param {Iterable|Object} collection Collection of iterators
* @param {string} [finish = 'early'] Flag determining when iteration will finish.
*
* @returns {itbl._Wrapper} Iterable containing collection of values
* @example
*
* let mySet = new Set();
* mySet.add(1);
* mySet.add(Math);
*
* [...itbl.combine([['a','b','c'], mySet, ['alpha','beta', 'gamma']])];
* // -> [['a', 1, 'alpha'], ['b', Math, 'beta']]
*
* // with `finish === late`
* [...itbl.combine([['a','b','c'], ['alpha','beta', 'gamma'], mySet], 'late')];
* // [['a', 1, 'alpha'], ['b', Math, 'beta'], ['c', undefined, 'gamma']]
*
* let coordinates = itbl.combine({
* x: [1,2,3,4,5],
* y: [1,4,9,16,25],
* });
*
* for(let coor of coordinates) {
* context.lineTo(coor.x, coor.y);
* }
*
* // more concise syntax using object destructuring
* for(let {x, y} of coordinates) {
* context.lineTo(x,y);
* }
*
*/
const combine = function combine(collection, finish) {
// TODO potential infinite loop if an iterator changes it's mind about whether it is done or not
let finishLate = false,
finishTogether = false;
switch (finish) {
case undefined:
case null:
case 'e':
case 'early':
break;
case 'l':
case 'late':
finishLate = true;
break;
case 't':
case 'together':
finishTogether = true;
break;
default:
throw new Error('`itbl.combine()`: `finish` is not recognised');
}
let combiningFunction = isIterable(collection)
? _iterableCombine
: _objectCombine;
return _generateIterable(function() {
let rawCombined = combiningFunction(collection);
return {
next: function() {
let { values, returnValues, anyDone, allDone } = rawCombined();
if ((!finishLate && anyDone) || allDone) {
if (finishTogether && !allDone) {
throw new Error("`itbl.combine()`: iterables combined with `finish === 'together'` have not finished together");
}
return {
value: returnValues,
done: true,
};
}
return {
value: values,
done: false,
};
},
};
});
};
/**
* Combines all `object`'s own enumerable values (which must be iterators) into a single iterable containing objects
* containing values from each iterable in `object`.
*
*
*
* @private
* @static
* @memberof itbl
* @since 0.1.0
* @param {Object} object Collection of iterators
*
* @returns {itbl._Wrapper} Iterable containing collection of values.
* @throws {Error} Throws an error if any own enumerable values of `object` are not enumerable.
*
*/
function _objectCombine(object) {
let iterators = {};
for (let key of Object.keys(object)) {
iterators[key] = _getIterator(object[key], 'combine', `\`collection.${key}\` is not an iterator`);
}
let returnValues = {};
return function() {
let values = {},
anyDone = false,
allDone = true;
for (let key of Object.keys(iterators)) {
let step = iterators[key].next();
returnValues[key] = step.done ? step.value : returnValues[key];
values [key] = !step.done ? step.value : undefined;
anyDone = anyDone || step.done;
allDone = allDone && step.done;
}
return { values, returnValues, anyDone, allDone };
};
}
/**
* An iterable containing integers from 0 to infinity
*
* @type {itbl}
* @const
*
* @example
*
* let set = new Set([1, 2, 3, 4, 'iyj', Math]);
*
* for (let [value, index] of itbl.combine([set, itbl.indexes])) {
* console.log('index: ' + value);
* }
*
*/
const indexes = _generateIterable(function() {
let i = 0;
return {
next() {
return {
value: i++,
done: false,
};
},
};
});
/**
* An iterable containing integers from 1 to infinity
*
* @type {itbl}
* @const
*
* @example
*
* let squares = itbl.integers.map( i => i*i );
*
*/
const integers = _generateIterable(function() {
let i = 1;
return {
next() {
return {
value: i++,
done: false,
};
},
};
});
/**
* Reverts the `itbl` variable to its previous value and returns a reference to
* the `itbl` function.
*
* @static
* @since 2.0.0
* @memberof itbl
* @returns {itbl} Returns the `itbl` function.
* @example
*
* var IterableUtil = itbl.noConflict();
*/
function noConflict() {
if (root.itbl === this) {
root.itbl = oldItbl;
}
return this;
}
Object.assign(itbl, {
combine,
filter,
indexes,
integers,
isIterable,
isIterator,
itbl,
noConflict,
map,
wrap,
}, EXPOSE_INTERNAL
? {
_wrapIterable,
_wrapIterator,
_generateIterable,
_getIterator,
_Wrapper,
}
: {});
/*--------------------------------------------------------------------------*/
// Export itbl.
// Some AMD build optimizers, like r.js, check for condition patterns like:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose itbl on the global object to prevent errors when itbl is
// loaded by a script tag in the presence of an AMD loader.
// See http://requirejs.org/docs/errors.html#mismatch for more details.
// Use `itbl.noConflict` to remove Lodash from the global object.
root.itbl = itbl;
// Define as a module.
define('itbl', function() {
return itbl;
});
}
// Check for `exports` after `define` in case a build optimizer adds it.
else if (freeModule) {
// Export for Node.js.
freeModule.exports = itbl;
// Export for CommonJS support.
freeExports.itbl = itbl;
}
else {
// Export to the global object.
root.itbl = itbl;
}
}.call(this));