UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

1 lines 131 kB
["^ ","~:resource-id",["~:shadow.build.classpath/resource","goog/iter/iter.js"],"~:js","goog.provide(\"goog.iter\");\ngoog.provide(\"goog.iter.Iterable\");\ngoog.provide(\"goog.iter.Iterator\");\ngoog.provide(\"goog.iter.StopIteration\");\ngoog.require(\"goog.array\");\ngoog.require(\"goog.asserts\");\ngoog.require(\"goog.functions\");\ngoog.require(\"goog.math\");\ngoog.iter.Iterable;\ngoog.iter.StopIteration = \"StopIteration\" in goog.global ? goog.global[\"StopIteration\"] : {message:\"StopIteration\", stack:\"\"};\ngoog.iter.Iterator = function() {\n};\ngoog.iter.Iterator.prototype.next = function() {\n throw goog.iter.StopIteration;\n};\ngoog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {\n return this;\n};\ngoog.iter.toIterator = function(iterable) {\n if (iterable instanceof goog.iter.Iterator) {\n return iterable;\n }\n if (typeof iterable.__iterator__ == \"function\") {\n return iterable.__iterator__(false);\n }\n if (goog.isArrayLike(iterable)) {\n var like = iterable;\n var i = 0;\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n while (true) {\n if (i >= like.length) {\n throw goog.iter.StopIteration;\n }\n if (!(i in like)) {\n i++;\n continue;\n }\n return like[i++];\n }\n };\n return newIter;\n }\n throw new Error(\"Not implemented\");\n};\ngoog.iter.forEach = function(iterable, f, opt_obj) {\n if (goog.isArrayLike(iterable)) {\n try {\n goog.array.forEach(iterable, f, opt_obj);\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n } else {\n iterable = goog.iter.toIterator(iterable);\n try {\n while (true) {\n f.call(opt_obj, iterable.next(), undefined, iterable);\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n }\n};\ngoog.iter.filter = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n while (true) {\n var val = iterator.next();\n if (f.call(opt_obj, val, undefined, iterator)) {\n return val;\n }\n }\n };\n return newIter;\n};\ngoog.iter.filterFalse = function(iterable, f, opt_obj) {\n return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);\n};\ngoog.iter.range = function(startOrStop, opt_stop, opt_step) {\n var start = 0;\n var stop = startOrStop;\n var step = opt_step || 1;\n if (arguments.length > 1) {\n start = startOrStop;\n stop = +opt_stop;\n }\n if (step == 0) {\n throw new Error(\"Range step argument must not be zero\");\n }\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n if (step > 0 && start >= stop || step < 0 && start <= stop) {\n throw goog.iter.StopIteration;\n }\n var rv = start;\n start += step;\n return rv;\n };\n return newIter;\n};\ngoog.iter.join = function(iterable, deliminator) {\n return goog.iter.toArray(iterable).join(deliminator);\n};\ngoog.iter.map = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n var val = iterator.next();\n return f.call(opt_obj, val, undefined, iterator);\n };\n return newIter;\n};\ngoog.iter.reduce = function(iterable, f, val, opt_obj) {\n var rval = val;\n goog.iter.forEach(iterable, function(val) {\n rval = f.call(opt_obj, rval, val);\n });\n return rval;\n};\ngoog.iter.some = function(iterable, f, opt_obj) {\n iterable = goog.iter.toIterator(iterable);\n try {\n while (true) {\n if (f.call(opt_obj, iterable.next(), undefined, iterable)) {\n return true;\n }\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n return false;\n};\ngoog.iter.every = function(iterable, f, opt_obj) {\n iterable = goog.iter.toIterator(iterable);\n try {\n while (true) {\n if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {\n return false;\n }\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n return true;\n};\ngoog.iter.chain = function(var_args) {\n return goog.iter.chainFromIterable(arguments);\n};\ngoog.iter.chainFromIterable = function(iterable) {\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator;\n var current = null;\n iter.next = function() {\n while (true) {\n if (current == null) {\n var it = iterator.next();\n current = goog.iter.toIterator(it);\n }\n try {\n return current.next();\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n current = null;\n }\n }\n };\n return iter;\n};\ngoog.iter.dropWhile = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n var dropping = true;\n newIter.next = function() {\n while (true) {\n var val = iterator.next();\n if (dropping && f.call(opt_obj, val, undefined, iterator)) {\n continue;\n } else {\n dropping = false;\n }\n return val;\n }\n };\n return newIter;\n};\ngoog.iter.takeWhile = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator;\n iter.next = function() {\n var val = iterator.next();\n if (f.call(opt_obj, val, undefined, iterator)) {\n return val;\n }\n throw goog.iter.StopIteration;\n };\n return iter;\n};\ngoog.iter.toArray = function(iterable) {\n if (goog.isArrayLike(iterable)) {\n return goog.array.toArray(iterable);\n }\n iterable = goog.iter.toIterator(iterable);\n var array = [];\n goog.iter.forEach(iterable, function(val) {\n array.push(val);\n });\n return array;\n};\ngoog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {\n var fillValue = {};\n var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);\n var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;\n return goog.iter.every(pairs, function(pair) {\n return equalsFn(pair[0], pair[1]);\n });\n};\ngoog.iter.nextOrValue = function(iterable, defaultValue) {\n try {\n return goog.iter.toIterator(iterable).next();\n } catch (e) {\n if (e != goog.iter.StopIteration) {\n throw e;\n }\n return defaultValue;\n }\n};\ngoog.iter.product = function(var_args) {\n var someArrayEmpty = goog.array.some(arguments, function(arr) {\n return !arr.length;\n });\n if (someArrayEmpty || !arguments.length) {\n return new goog.iter.Iterator;\n }\n var iter = new goog.iter.Iterator;\n var arrays = arguments;\n var indicies = goog.array.repeat(0, arrays.length);\n iter.next = function() {\n if (indicies) {\n var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {\n return arrays[arrayIndex][valueIndex];\n });\n for (var i = indicies.length - 1; i >= 0; i--) {\n goog.asserts.assert(indicies);\n if (indicies[i] < arrays[i].length - 1) {\n indicies[i]++;\n break;\n }\n if (i == 0) {\n indicies = null;\n break;\n }\n indicies[i] = 0;\n }\n return retVal;\n }\n throw goog.iter.StopIteration;\n };\n return iter;\n};\ngoog.iter.cycle = function(iterable) {\n var baseIterator = goog.iter.toIterator(iterable);\n var cache = [];\n var cacheIndex = 0;\n var iter = new goog.iter.Iterator;\n var useCache = false;\n iter.next = function() {\n var returnElement = null;\n if (!useCache) {\n try {\n returnElement = baseIterator.next();\n cache.push(returnElement);\n return returnElement;\n } catch (e) {\n if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {\n throw e;\n }\n useCache = true;\n }\n }\n returnElement = cache[cacheIndex];\n cacheIndex = (cacheIndex + 1) % cache.length;\n return returnElement;\n };\n return iter;\n};\ngoog.iter.count = function(opt_start, opt_step) {\n var counter = opt_start || 0;\n var step = opt_step !== undefined ? opt_step : 1;\n var iter = new goog.iter.Iterator;\n iter.next = function() {\n var returnValue = counter;\n counter += step;\n return returnValue;\n };\n return iter;\n};\ngoog.iter.repeat = function(value) {\n var iter = new goog.iter.Iterator;\n iter.next = goog.functions.constant(value);\n return iter;\n};\ngoog.iter.accumulate = function(iterable) {\n var iterator = goog.iter.toIterator(iterable);\n var total = 0;\n var iter = new goog.iter.Iterator;\n iter.next = function() {\n total += iterator.next();\n return total;\n };\n return iter;\n};\ngoog.iter.zip = function(var_args) {\n var args = arguments;\n var iter = new goog.iter.Iterator;\n if (args.length > 0) {\n var iterators = goog.array.map(args, goog.iter.toIterator);\n iter.next = function() {\n var arr = goog.array.map(iterators, function(it) {\n return it.next();\n });\n return arr;\n };\n }\n return iter;\n};\ngoog.iter.zipLongest = function(fillValue, var_args) {\n var args = goog.array.slice(arguments, 1);\n var iter = new goog.iter.Iterator;\n if (args.length > 0) {\n var iterators = goog.array.map(args, goog.iter.toIterator);\n iter.next = function() {\n var iteratorsHaveValues = false;\n var arr = goog.array.map(iterators, function(it) {\n var returnValue;\n try {\n returnValue = it.next();\n iteratorsHaveValues = true;\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n returnValue = fillValue;\n }\n return returnValue;\n });\n if (!iteratorsHaveValues) {\n throw goog.iter.StopIteration;\n }\n return arr;\n };\n }\n return iter;\n};\ngoog.iter.compress = function(iterable, selectors) {\n var selectorIterator = goog.iter.toIterator(selectors);\n return goog.iter.filter(iterable, function() {\n return !!selectorIterator.next();\n });\n};\ngoog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {\n this.iterator = goog.iter.toIterator(iterable);\n this.keyFunc = opt_keyFunc || goog.functions.identity;\n this.targetKey;\n this.currentKey;\n this.currentValue;\n};\ngoog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);\ngoog.iter.GroupByIterator_.prototype.next = function() {\n while (this.currentKey == this.targetKey) {\n this.currentValue = this.iterator.next();\n this.currentKey = this.keyFunc(this.currentValue);\n }\n this.targetKey = this.currentKey;\n return [this.currentKey, this.groupItems_(this.targetKey)];\n};\ngoog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {\n var arr = [];\n while (this.currentKey == targetKey) {\n arr.push(this.currentValue);\n try {\n this.currentValue = this.iterator.next();\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n break;\n }\n this.currentKey = this.keyFunc(this.currentValue);\n }\n return arr;\n};\ngoog.iter.groupBy = function(iterable, opt_keyFunc) {\n return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);\n};\ngoog.iter.starMap = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator;\n iter.next = function() {\n var args = goog.iter.toArray(iterator.next());\n return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));\n };\n return iter;\n};\ngoog.iter.tee = function(iterable, opt_num) {\n var iterator = goog.iter.toIterator(iterable);\n var num = typeof opt_num === \"number\" ? opt_num : 2;\n var buffers = goog.array.map(goog.array.range(num), function() {\n return [];\n });\n var addNextIteratorValueToBuffers = function() {\n var val = iterator.next();\n goog.array.forEach(buffers, function(buffer) {\n buffer.push(val);\n });\n };\n var createIterator = function(buffer) {\n var iter = new goog.iter.Iterator;\n iter.next = function() {\n if (goog.array.isEmpty(buffer)) {\n addNextIteratorValueToBuffers();\n }\n goog.asserts.assert(!goog.array.isEmpty(buffer));\n return buffer.shift();\n };\n return iter;\n };\n return goog.array.map(buffers, createIterator);\n};\ngoog.iter.enumerate = function(iterable, opt_start) {\n return goog.iter.zip(goog.iter.count(opt_start), iterable);\n};\ngoog.iter.limit = function(iterable, limitSize) {\n goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator;\n var remaining = limitSize;\n iter.next = function() {\n if (remaining-- > 0) {\n return iterator.next();\n }\n throw goog.iter.StopIteration;\n };\n return iter;\n};\ngoog.iter.consume = function(iterable, count) {\n goog.asserts.assert(goog.math.isInt(count) && count >= 0);\n var iterator = goog.iter.toIterator(iterable);\n while (count-- > 0) {\n goog.iter.nextOrValue(iterator, null);\n }\n return iterator;\n};\ngoog.iter.slice = function(iterable, start, opt_end) {\n goog.asserts.assert(goog.math.isInt(start) && start >= 0);\n var iterator = goog.iter.consume(iterable, start);\n if (typeof opt_end === \"number\") {\n goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start);\n iterator = goog.iter.limit(iterator, opt_end - start);\n }\n return iterator;\n};\ngoog.iter.hasDuplicates_ = function(arr) {\n var deduped = [];\n goog.array.removeDuplicates(arr, deduped);\n return arr.length != deduped.length;\n};\ngoog.iter.permutations = function(iterable, opt_length) {\n var elements = goog.iter.toArray(iterable);\n var length = typeof opt_length === \"number\" ? opt_length : elements.length;\n var sets = goog.array.repeat(elements, length);\n var product = goog.iter.product.apply(undefined, sets);\n return goog.iter.filter(product, function(arr) {\n return !goog.iter.hasDuplicates_(arr);\n });\n};\ngoog.iter.combinations = function(iterable, length) {\n var elements = goog.iter.toArray(iterable);\n var indexes = goog.iter.range(elements.length);\n var indexIterator = goog.iter.permutations(indexes, length);\n var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {\n return goog.array.isSorted(arr);\n });\n var iter = new goog.iter.Iterator;\n function getIndexFromElements(index) {\n return elements[index];\n }\n iter.next = function() {\n return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);\n };\n return iter;\n};\ngoog.iter.combinationsWithReplacement = function(iterable, length) {\n var elements = goog.iter.toArray(iterable);\n var indexes = goog.array.range(elements.length);\n var sets = goog.array.repeat(indexes, length);\n var indexIterator = goog.iter.product.apply(undefined, sets);\n var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {\n return goog.array.isSorted(arr);\n });\n var iter = new goog.iter.Iterator;\n function getIndexFromElements(index) {\n return elements[index];\n }\n iter.next = function() {\n return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);\n };\n return iter;\n};\n","~:source","// Copyright 2007 The Closure Library Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS-IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * @fileoverview Python style iteration utilities.\n * @author arv@google.com (Erik Arvidsson)\n */\n\n\ngoog.provide('goog.iter');\ngoog.provide('goog.iter.Iterable');\ngoog.provide('goog.iter.Iterator');\ngoog.provide('goog.iter.StopIteration');\n\ngoog.require('goog.array');\ngoog.require('goog.asserts');\ngoog.require('goog.functions');\ngoog.require('goog.math');\n\n\n/**\n * @typedef {{length:number}|{__iterator__}}\n */\ngoog.iter.Iterable;\n\n\n/**\n * Singleton Error object that is used to terminate iterations.\n * @const {!Error}\n */\ngoog.iter.StopIteration = ('StopIteration' in goog.global) ?\n // For script engines that support legacy iterators.\n goog.global['StopIteration'] :\n {message: 'StopIteration', stack: ''};\n\n\n\n/**\n * Class/interface for iterators. An iterator needs to implement a `next`\n * method and it needs to throw a `goog.iter.StopIteration` when the\n * iteration passes beyond the end. Iterators have no `hasNext` method.\n * It is recommended to always use the helper functions to iterate over the\n * iterator or in case you are only targeting JavaScript 1.7 for in loops.\n * @constructor\n * @template VALUE\n */\ngoog.iter.Iterator = function() {};\n\n\n/**\n * Returns the next value of the iteration. This will throw the object\n * {@see goog.iter.StopIteration} when the iteration passes the end.\n * @return {VALUE} Any object or value.\n */\ngoog.iter.Iterator.prototype.next = function() {\n throw goog.iter.StopIteration;\n};\n\n\n/**\n * Returns the `Iterator` object itself. This is used to implement\n * the iterator protocol in JavaScript 1.7\n * @param {boolean=} opt_keys Whether to return the keys or values. Default is\n * to only return the values. This is being used by the for-in loop (true)\n * and the for-each-in loop (false). Even though the param gives a hint\n * about what the iterator will return there is no guarantee that it will\n * return the keys when true is passed.\n * @return {!goog.iter.Iterator<VALUE>} The object itself.\n */\ngoog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {\n return this;\n};\n\n\n/**\n * Returns an iterator that knows how to iterate over the values in the object.\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable If the\n * object is an iterator it will be returned as is. If the object has an\n * `__iterator__` method that will be called to get the value\n * iterator. If the object is an array-like object we create an iterator\n * for that.\n * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate\n * over the values in `iterable`.\n * @template VALUE\n */\ngoog.iter.toIterator = function(iterable) {\n if (iterable instanceof goog.iter.Iterator) {\n return iterable;\n }\n if (typeof iterable.__iterator__ == 'function') {\n return /** @type {{__iterator__:function(this:?, boolean=)}} */ (iterable)\n .__iterator__(false);\n }\n if (goog.isArrayLike(iterable)) {\n var like = /** @type {!IArrayLike<number|string>} */ (iterable);\n var i = 0;\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n while (true) {\n if (i >= like.length) {\n throw goog.iter.StopIteration;\n }\n // Don't include deleted elements.\n if (!(i in like)) {\n i++;\n continue;\n }\n return like[i++];\n }\n };\n return newIter;\n }\n\n\n // TODO(arv): Should we fall back on goog.structs.getValues()?\n throw new Error('Not implemented');\n};\n\n\n/**\n * Calls a function for each element in the iterator with the element of the\n * iterator passed as argument.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to iterate over. If the iterable is an object `toIterator` will be\n * called on it.\n * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f\n * The function to call for every element. This function takes 3 arguments\n * (the element, undefined, and the iterator) and the return value is\n * irrelevant. The reason for passing undefined as the second argument is\n * so that the same function can be used in {@see goog.array.forEach} as\n * well as others. The third parameter is of type \"number\" for\n * arraylike objects, undefined, otherwise.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @template THIS, VALUE\n */\ngoog.iter.forEach = function(iterable, f, opt_obj) {\n if (goog.isArrayLike(iterable)) {\n\n try {\n // NOTES: this passes the index number to the second parameter\n // of the callback contrary to the documentation above.\n goog.array.forEach(\n /** @type {IArrayLike<?>} */ (iterable), f, opt_obj);\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n } else {\n iterable = goog.iter.toIterator(iterable);\n\n try {\n while (true) {\n f.call(opt_obj, iterable.next(), undefined, iterable);\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n }\n};\n\n\n/**\n * Calls a function for every element in the iterator, and if the function\n * returns true adds the element to a new iterator.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to iterate over.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every element. This function takes 3 arguments\n * (the element, undefined, and the iterator) and should return a boolean.\n * If the return value is true the element will be included in the returned\n * iterator. If it is false the element is not included.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements\n * that passed the test are present.\n * @template THIS, VALUE\n */\ngoog.iter.filter = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n while (true) {\n var val = iterator.next();\n if (f.call(opt_obj, val, undefined, iterator)) {\n return val;\n }\n }\n };\n return newIter;\n};\n\n\n/**\n * Calls a function for every element in the iterator, and if the function\n * returns false adds the element to a new iterator.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to iterate over.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every element. This function takes 3 arguments\n * (the element, undefined, and the iterator) and should return a boolean.\n * If the return value is false the element will be included in the returned\n * iterator. If it is true the element is not included.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements\n * that did not pass the test are present.\n * @template THIS, VALUE\n */\ngoog.iter.filterFalse = function(iterable, f, opt_obj) {\n return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);\n};\n\n\n/**\n * Creates a new iterator that returns the values in a range. This function\n * can take 1, 2 or 3 arguments:\n * <pre>\n * range(5) same as range(0, 5, 1)\n * range(2, 5) same as range(2, 5, 1)\n * </pre>\n *\n * @param {number} startOrStop The stop value if only one argument is provided.\n * The start value if 2 or more arguments are provided. If only one\n * argument is used the start value is 0.\n * @param {number=} opt_stop The stop value. If left out then the first\n * argument is used as the stop value.\n * @param {number=} opt_step The number to increment with between each call to\n * next. This can be negative.\n * @return {!goog.iter.Iterator<number>} A new iterator that returns the values\n * in the range.\n */\ngoog.iter.range = function(startOrStop, opt_stop, opt_step) {\n var start = 0;\n var stop = startOrStop;\n var step = opt_step || 1;\n if (arguments.length > 1) {\n start = startOrStop;\n stop = +opt_stop;\n }\n if (step == 0) {\n throw new Error('Range step argument must not be zero');\n }\n\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n if (step > 0 && start >= stop || step < 0 && start <= stop) {\n throw goog.iter.StopIteration;\n }\n var rv = start;\n start += step;\n return rv;\n };\n return newIter;\n};\n\n\n/**\n * Joins the values in a iterator with a delimiter.\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to get the values from.\n * @param {string} deliminator The text to put between the values.\n * @return {string} The joined value string.\n * @template VALUE\n */\ngoog.iter.join = function(iterable, deliminator) {\n return goog.iter.toArray(iterable).join(deliminator);\n};\n\n\n/**\n * For every element in the iterator call a function and return a new iterator\n * with that value.\n *\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The\n * iterator to iterate over.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f\n * The function to call for every element. This function takes 3 arguments\n * (the element, undefined, and the iterator) and should return a new value.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the\n * results of applying the function to each element in the original\n * iterator.\n * @template THIS, VALUE, RESULT\n */\ngoog.iter.map = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n newIter.next = function() {\n var val = iterator.next();\n return f.call(opt_obj, val, undefined, iterator);\n };\n return newIter;\n};\n\n\n/**\n * Passes every element of an iterator into a function and accumulates the\n * result.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to iterate over.\n * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for\n * every element. This function takes 2 arguments (the function's previous\n * result or the initial value, and the value of the current element).\n * function(previousValue, currentElement) : newValue.\n * @param {VALUE} val The initial value to pass into the function on the first\n * call.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * f.\n * @return {VALUE} Result of evaluating f repeatedly across the values of\n * the iterator.\n * @template THIS, VALUE\n */\ngoog.iter.reduce = function(iterable, f, val, opt_obj) {\n var rval = val;\n goog.iter.forEach(\n iterable, function(val) { rval = f.call(opt_obj, rval, val); });\n return rval;\n};\n\n\n/**\n * Goes through the values in the iterator. Calls f for each of these, and if\n * any of them returns true, this returns true (without checking the rest). If\n * all return false this will return false.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * object.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every value. This function takes 3 arguments\n * (the value, undefined, and the iterator) and should return a boolean.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {boolean} true if any value passes the test.\n * @template THIS, VALUE\n */\ngoog.iter.some = function(iterable, f, opt_obj) {\n iterable = goog.iter.toIterator(iterable);\n\n try {\n while (true) {\n if (f.call(opt_obj, iterable.next(), undefined, iterable)) {\n return true;\n }\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n return false;\n};\n\n\n/**\n * Goes through the values in the iterator. Calls f for each of these and if any\n * of them returns false this returns false (without checking the rest). If all\n * return true this will return true.\n *\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * object.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every value. This function takes 3 arguments\n * (the value, undefined, and the iterator) and should return a boolean.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {boolean} true if every value passes the test.\n * @template THIS, VALUE\n */\ngoog.iter.every = function(iterable, f, opt_obj) {\n iterable = goog.iter.toIterator(iterable);\n\n try {\n while (true) {\n if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {\n return false;\n }\n }\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n }\n return true;\n};\n\n\n/**\n * Takes zero or more iterables and returns one iterator that will iterate over\n * them in the order chained.\n * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any\n * number of iterable objects.\n * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will\n * iterate over all the given iterables' contents.\n * @template VALUE\n */\ngoog.iter.chain = function(var_args) {\n return goog.iter.chainFromIterable(arguments);\n};\n\n\n/**\n * Takes a single iterable containing zero or more iterables and returns one\n * iterator that will iterate over each one in the order given.\n * @see https://goo.gl/5NRp5d\n * @param {goog.iter.Iterator<?>|goog.iter.Iterable} iterable The iterable of\n * iterables to chain.\n * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will\n * iterate over all the contents of the iterables contained within\n * `iterable`.\n * @template VALUE\n */\ngoog.iter.chainFromIterable = function(iterable) {\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator();\n var current = null;\n\n iter.next = function() {\n while (true) {\n if (current == null) {\n var it = iterator.next();\n current = goog.iter.toIterator(it);\n }\n try {\n return current.next();\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n current = null;\n }\n }\n };\n\n return iter;\n};\n\n\n/**\n * Builds a new iterator that iterates over the original, but skips elements as\n * long as a supplied function returns true.\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * object.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every value. This function takes 3 arguments\n * (the value, undefined, and the iterator) and should return a boolean.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within\n * `f`.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from\n * the original iterator as long as `f` is true.\n * @template THIS, VALUE\n */\ngoog.iter.dropWhile = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var newIter = new goog.iter.Iterator;\n var dropping = true;\n newIter.next = function() {\n while (true) {\n var val = iterator.next();\n if (dropping && f.call(opt_obj, val, undefined, iterator)) {\n continue;\n } else {\n dropping = false;\n }\n return val;\n }\n };\n return newIter;\n};\n\n\n/**\n * Builds a new iterator that iterates over the original, but only as long as a\n * supplied function returns true.\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * object.\n * @param {\n * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f\n * The function to call for every value. This function takes 3 arguments\n * (the value, undefined, and the iterator) and should return a boolean.\n * @param {THIS=} opt_obj This is used as the 'this' object in f when called.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in\n * the original iterator as long as the function is true.\n * @template THIS, VALUE\n */\ngoog.iter.takeWhile = function(iterable, f, opt_obj) {\n var iterator = goog.iter.toIterator(iterable);\n var iter = new goog.iter.Iterator();\n iter.next = function() {\n var val = iterator.next();\n if (f.call(opt_obj, val, undefined, iterator)) {\n return val;\n }\n throw goog.iter.StopIteration;\n };\n return iter;\n};\n\n\n/**\n * Converts the iterator to an array\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator\n * to convert to an array.\n * @return {!Array<VALUE>} An array of the elements the iterator iterates over.\n * @template VALUE\n */\ngoog.iter.toArray = function(iterable) {\n // Fast path for array-like.\n if (goog.isArrayLike(iterable)) {\n return goog.array.toArray(/** @type {!IArrayLike<?>} */ (iterable));\n }\n iterable = goog.iter.toIterator(iterable);\n var array = [];\n goog.iter.forEach(iterable, function(val) { array.push(val); });\n return array;\n};\n\n\n/**\n * Iterates over two iterables and returns true if they contain the same\n * sequence of elements and have the same length.\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first\n * iterable object.\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second\n * iterable object.\n * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison\n * function.\n * Should take two arguments to compare, and return true if the arguments\n * are equal. Defaults to {@link goog.array.defaultCompareEquality} which\n * compares the elements using the built-in '===' operator.\n * @return {boolean} true if the iterables contain the same sequence of elements\n * and have the same length.\n * @template VALUE\n */\ngoog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {\n var fillValue = {};\n var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);\n var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;\n return goog.iter.every(\n pairs, function(pair) { return equalsFn(pair[0], pair[1]); });\n};\n\n\n/**\n * Advances the iterator to the next position, returning the given default value\n * instead of throwing an exception if the iterator has no more entries.\n * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable\n * object.\n * @param {VALUE} defaultValue The value to return if the iterator is empty.\n * @return {VALUE} The next item in the iteration, or defaultValue if the\n * iterator was empty.\n * @template VALUE\n */\ngoog.iter.nextOrValue = function(iterable, defaultValue) {\n try {\n return goog.iter.toIterator(iterable).next();\n } catch (e) {\n if (e != goog.iter.StopIteration) {\n throw e;\n }\n return defaultValue;\n }\n};\n\n\n/**\n * Cartesian product of zero or more sets. Gives an iterator that gives every\n * combination of one element chosen from each set. For example,\n * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]).\n * @see http://docs.python.org/library/itertools.html#itertools.product\n * @param {...!IArrayLike<VALUE>} var_args Zero or more sets, as\n * arrays.\n * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each\n * n-tuple (as an array).\n * @template VALUE\n */\ngoog.iter.product = function(var_args) {\n var someArrayEmpty =\n goog.array.some(arguments, function(arr) { return !arr.length; });\n\n // An empty set in a cartesian product gives an empty set.\n if (someArrayEmpty || !arguments.length) {\n return new goog.iter.Iterator();\n }\n\n var iter = new goog.iter.Iterator();\n var arrays = arguments;\n\n // The first indices are [0, 0, ...]\n /** @type {?Array<number>} */\n var indicies = goog.array.repeat(0, arrays.length);\n\n iter.next = function() {\n\n if (indicies) {\n var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {\n return arrays[arrayIndex][valueIndex];\n });\n\n // Generate the next-largest indices for the next call.\n // Increase the rightmost index. If it goes over, increase the next\n // rightmost (like carry-over addition).\n for (var i = indicies.length - 1; i >= 0; i--) {\n // Assertion prevents compiler warning below.\n goog.asserts.assert(indicies);\n if (indicies[i] < arrays[i].length - 1) {\n indicies[i]++;\n break;\n }\n\n // We're at the last indices (the last element of every array), so\n // the iteration is over on the next call.\n if (i == 0) {\n indicies = null;\n break;\n }\n // Reset the index in this column and loop back to increment the\n // next one.\n indicies[i] = 0;\n }\n return retVal;\n }\n\n throw goog.iter.StopIteration;\n };\n\n return iter;\n};\n\n\n/**\n * Create an iterator to cycle over the iterable's elements indefinitely.\n * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ...\n * @see: http://docs.python.org/library/itertools.html#itertools.cycle.\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The\n * iterable object.\n * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely\n * over the values in `iterable`.\n * @template VALUE\n */\ngoog.iter.cycle = function(iterable) {\n var baseIterator = goog.iter.toIterator(iterable);\n\n // We maintain a cache to store the iterable elements as we iterate\n // over them. The cache is used to return elements once we have\n // iterated over the iterable once.\n var cache = [];\n var cacheIndex = 0;\n\n var iter = new goog.iter.Iterator();\n\n // This flag is set after the iterable is iterated over once\n var useCache = false;\n\n iter.next = function() {\n var returnElement = null;\n\n // Pull elements off the original iterator if not using cache\n if (!useCache) {\n try {\n // Return the element from the iterable\n returnElement = baseIterator.next();\n cache.push(returnElement);\n return returnElement;\n } catch (e) {\n // If an exception other than StopIteration is thrown\n // or if there are no elements to iterate over (the iterable was empty)\n // throw an exception\n if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {\n throw e;\n }\n // set useCache to true after we know that a 'StopIteration' exception\n // was thrown and the cache is not empty (to handle the 'empty iterable'\n // use case)\n useCache = true;\n }\n }\n\n returnElement = cache[cacheIndex];\n cacheIndex = (cacheIndex + 1) % cache.length;\n\n return returnElement;\n };\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that counts indefinitely from a starting value.\n * @see http://docs.python.org/2/library/itertools.html#itertools.count\n * @param {number=} opt_start The starting value. Default is 0.\n * @param {number=} opt_step The number to increment with between each call to\n * next. Negative and floating point numbers are allowed. Default is 1.\n * @return {!goog.iter.Iterator<number>} A new iterator that returns the values\n * in the series.\n */\ngoog.iter.count = function(opt_start, opt_step) {\n var counter = opt_start || 0;\n var step = (opt_step !== undefined) ? opt_step : 1;\n var iter = new goog.iter.Iterator();\n\n iter.next = function() {\n var returnValue = counter;\n counter += step;\n return returnValue;\n };\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that returns the same object or value repeatedly.\n * @param {VALUE} value Any object or value to repeat.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the\n * repeated value.\n * @template VALUE\n */\ngoog.iter.repeat = function(value) {\n var iter = new goog.iter.Iterator();\n\n iter.next = goog.functions.constant(value);\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that returns running totals from the numbers in\n * `iterable`. For example, the array {@code [1, 2, 3, 4, 5]} yields\n * {@code 1 -> 3 -> 6 -> 10 -> 15}.\n * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate\n * @param {!goog.iter.Iterator<number>|!goog.iter.Iterable} iterable The\n * iterable of numbers to accumulate.\n * @return {!goog.iter.Iterator<number>} A new iterator that returns the\n * numbers in the series.\n */\ngoog.iter.accumulate = function(iterable) {\n var iterator = goog.iter.toIterator(iterable);\n var total = 0;\n var iter = new goog.iter.Iterator();\n\n iter.next = function() {\n total += iterator.next();\n return total;\n };\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that returns arrays containing the ith elements from the\n * provided iterables. The returned arrays will be the same size as the number\n * of iterables given in `var_args`. Once the shortest iterable is\n * exhausted, subsequent calls to `next()` will throw\n * `goog.iter.StopIteration`.\n * @see http://docs.python.org/2/library/itertools.html#itertools.izip\n * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any\n * number of iterable objects.\n * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns\n * arrays of elements from the provided iterables.\n * @template VALUE\n */\ngoog.iter.zip = function(var_args) {\n var args = arguments;\n var iter = new goog.iter.Iterator();\n\n if (args.length > 0) {\n var iterators = goog.array.map(args, goog.iter.toIterator);\n iter.next = function() {\n var arr = goog.array.map(iterators, function(it) { return it.next(); });\n return arr;\n };\n }\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that returns arrays containing the ith elements from the\n * provided iterables. The returned arrays will be the same size as the number\n * of iterables given in `var_args`. Shorter iterables will be extended\n * with `fillValue`. Once the longest iterable is exhausted, subsequent\n * calls to `next()` will throw `goog.iter.StopIteration`.\n * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest\n * @param {VALUE} fillValue The object or value used to fill shorter iterables.\n * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any\n * number of iterable objects.\n * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns\n * arrays of elements from the provided iterables.\n * @template VALUE\n */\ngoog.iter.zipLongest = function(fillValue, var_args) {\n var args = goog.array.slice(arguments, 1);\n var iter = new goog.iter.Iterator();\n\n if (args.length > 0) {\n var iterators = goog.array.map(args, goog.iter.toIterator);\n\n iter.next = function() {\n var iteratorsHaveValues = false; // false when all iterators are empty.\n var arr = goog.array.map(iterators, function(it) {\n var returnValue;\n try {\n returnValue = it.next();\n // Iterator had a value, so we've not exhausted the iterators.\n // Set flag accordingly.\n iteratorsHaveValues = true;\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n returnValue = fillValue;\n }\n return returnValue;\n });\n\n if (!iteratorsHaveValues) {\n throw goog.iter.StopIteration;\n }\n return arr;\n };\n }\n\n return iter;\n};\n\n\n/**\n * Creates an iterator that filters `iterable` based on a series of\n * `selectors`. On each call to `next()`, one item is taken from\n * both the `iterable` and `selectors` iterators. If the item from\n * `selectors` evaluates to true, the item from `iterable` is given.\n * Otherwise, it is skipped. Once either `iterable` or `selectors`\n * is exhausted, subsequent calls to `next()` will throw\n * `goog.iter.StopIteration`.\n * @see http://docs.python.org/2/library/itertools.html#itertools.compress\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The\n * iterable to filter.\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An\n * iterable of items to be evaluated in a boolean context to determine if\n * the corresponding element in `iterable` should be included in the\n * result.\n * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the\n * filtered values.\n * @template VALUE\n */\ngoog.iter.compress = function(iterable, selectors) {\n var selectorIterator = goog.iter.toIterator(selectors);\n\n return goog.iter.filter(\n iterable, function() { return !!selectorIterator.next(); });\n};\n\n\n\n/**\n * Implements the `goog.iter.groupBy` iterator.\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The\n * iterable to group.\n * @param {function(VALUE): KEY=} opt_keyFunc Optional function for\n * determining the key value for each group in the `iterable`. Default\n * is the identity function.\n * @constructor\n * @extends {goog.iter.Iterator<!Array<?>>}\n * @template KEY, VALUE\n * @private\n */\ngoog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {\n\n /**\n * The iterable to group, coerced to an iterator.\n * @type {!goog.iter.Iterator}\n */\n this.iterator = goog.iter.toIterator(iterable);\n\n /**\n * A function for determining the key value for each element in the iterable.\n * If no function is provided, the identity function is used and returns the\n * element unchanged.\n * @type {function(VALUE): KEY}\n */\n this.keyFunc = opt_keyFunc || goog.functions.identity;\n\n /**\n * The target key for determining the start of a group.\n * @type {KEY}\n */\n this.targetKey;\n\n /**\n * The current key visited during iteration.\n * @type {KEY}\n */\n this.currentKey;\n\n /**\n * The current value being added to the group.\n * @type {VALUE}\n */\n this.currentValue;\n};\ngoog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);\n\n\n/** @override */\ngoog.iter.GroupByIterator_.prototype.next = function() {\n while (this.currentKey == this.targetKey) {\n this.currentValue = this.iterator.next(); // Exits on StopIteration\n this.currentKey = this.keyFunc(this.currentValue);\n }\n this.targetKey = this.currentKey;\n return [this.currentKey, this.groupItems_(this.targetKey)];\n};\n\n\n/**\n * Performs the grouping of objects using the given key.\n * @param {KEY} targetKey The target key object for the group.\n * @return {!Array<VALUE>} An array of grouped objects.\n * @private\n */\ngoog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {\n var arr = [];\n while (this.currentKey == targetKey) {\n arr.push(this.currentValue);\n try {\n this.currentValue = this.iterator.next();\n } catch (ex) {\n if (ex !== goog.iter.StopIteration) {\n throw ex;\n }\n break;\n }\n this.currentKey = this.keyFunc(this.currentValue);\n }\n return arr;\n};\n\n\n/**\n * Creates an iterator that returns arrays containing elements from the\n * `iterable` grouped by a key value. For iterables with repeated\n * elements (i.e. sorted according to a particular key function), this function\n * has a `uniq`-like effect. For example, grouping the array:\n * {@code [A, B, B, C, C, A]} produces\n * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}.\n * @see http://docs.python.org/2/library/itertools.html#itertools.groupby\n * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The\n * iterable to group.\n * @param {function(VALUE): KEY=} opt_keyFunc Optional function for\n * determining the key value for each group in the `iterable`. Default\n * is the identity function.\n * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns\n * arrays of consecutive key and groups.\n * @template KEY, VALUE\n */\ngoog.iter.groupBy = function(iterable, opt_keyFunc) {\n return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);\n};\n\n\n/**\n * Gives an iterator that gives the result of calling the given function\n * <code>f</code> with the arguments taken from the next element from\n * <code>iterable</code> (the elements are expected to also be iterables).\n *\n * Similar to {@see goog.iter.map} but allows the function to accept multiple\n * arguments from the iterable.\n *\n * @param {!goog.iter.Iterator<?>|!goog.iter.Iterable} iterable The iterable of\n * iterables to iterate over.\n * @param {function(this:THIS,...*):RESULT} f The function to call for every\n * element. This function takes N+2 arguments, where N represents the\n * number of items from the next element of the iterable. The two\n * additional argument