"use strict";
/**
* This is the rq standard library as implemented in Javascript.
*
* Note that the examples in this file are doctests. Any line with the format:
*
* <input> → <process> <args>* → <output>
*
* ...will be verified as part of the build.
* @module prelude
*/
// Regex for converting (most) lodash Array JSDoc:
// Search: "_\.(\w+)\(\[([^])]+?)\](?:, ([^)]+))?\);\n \* // => \[(.*)\]$"
// Replace: "$2 => $1($3) => $4"
var _ = require('lodash');
/**
* Passes through all of the values it sees untouched.
*
* @static
* @this rq.Context
* @example
* {"a": 2, "b": 3} → id → {"a": 2, "b": 3}
* true → id → true
*/
function* id() {
while (yield* this.pull()) {
yield* this.push(this.value);
}
}
/**
* Selects the field(s) at the specified path for each value in the stream.
*
* @static
* @this rq.Context
* @example
* {"a": {"b": {"c": 3}}} → select "/a/b" → {"c": 3}
* {"a": {"b": {"c": 3}}} → select "/a/x" → (empty)
*
* @param {string} path the field path to follow
*/
function* select(path) {
var self = this;
while (yield* this.pull()) {
var lenses = rq.util.path(this.value, path);
for (var i = 0; i < lenses.length; i++) {
var lens = lenses[i];
var value = lens.get();
yield* self.push(value);
}
}
}
/**
* Modifies the field at the specified path for each value in the stream, using the specified
* function.
*
* @static
* @this rq.Context
* @example
* {"a": {"b": 2, "c": true}} → modify "/a/b" (n => n + 2) → {"a": {"b": 4, "c": true}}
* {"a": {"b": 2, "c": true}} → modify "/a/x" (n => n + 2) → {"a": {"b": 2, "c": true}}
*
* @param {string} path the field path to follow
* @param {function(*): *} f the function to apply
*/
function* modify(path, f) {
while (yield* this.pull()) {
var lenses = rq.util.path(this.value, path);
for (var i = 0; i < lenses.length; i++) {
var lens = lenses[i];
lens.set(f(lens.get()));
}
yield* this.push(this.value);
}
}
/**
* Logs each value that passes through to the info log.
*
* @static
* @this rq.Context
*/
function* tee() {
while (yield* this.pull()) {
this.log.info(JSON.stringify(this.value));
yield* this.push(this.value);
}
}
/**
* Collects all of the values from the input stream into an array.
*
* @static
* @this rq.Context
* @example
* true [] 1 → collect → [true, [], 1]
*/
function* collect() {
yield* this.push((yield* this.collect()));
}
/**
* Spreads each array in the input stream into separate output values.
*
* @static
* @this rq.Context
* @example
* [1, 2] [3, 4] 5 → spread → 1 2 3 4 5
*/
function* spread() {
while (yield* this.pull()) {
if (Array.isArray(this.value)) {
yield* this.spread(this.value);
} else {
yield* this.push(this.value);
}
}
}
/**
* Counts the number of input elements.
*
* @static
* @this rq.Context
* @method
* @example
* 6.1 4.2 6.3 → count → 3
* "one" "two" "three" → count → 3
*/
var count = size;
/**
* Checks if `predicate` returns truthy for **all** elements of the input stream.
* Iteration is stopped once `predicate` returns falsey. The predicate is
* invoked with two arguments: (value, index).
*
* @static
* @this rq.Context
* @method
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* true 1 null "yes" → all (Boolean) → false
* // With index
* 1 2 3 → all (x, i) => { i + 1 == x } → true
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → all {"u": "b", "a": false} → false
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → all ["a", false] → true
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → all "a" → false
*/
var all = every;
/**
* Checks if `predicate` returns truthy for **any** element of the input stream.
* Iteration is stopped once `predicate` returns truthy. The predicate is
* invoked with two arguments: (value, index).
*
* @static
* @this rq.Context
* @method
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @example
* null 0 "yes" false → any (Boolean) → true
* // With index
* 5 1 8 → any (x, i) => { i == x } → true
* // The `matches` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → any {"u": "b", "a": false} → false
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → any ["a", false] → true
* // The `property` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → any "a" → true
*/
var any = some;
/**
* Creates a stream of elements, with the input sorted in ascending order. This
* method performs a stable sort, that is, it preserves the original sort order
* of equal elements.
*
* @static
* @this rq.Context
* @example
* 3 1 2 → sort → 1 2 3
*/
function* sort() {
yield* sortBy.call(this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Array ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a stream of elements split into groups the length of `size`.
* If the input stream can't be split evenly, the final chunk will be the remaining
* elements.
*
* @static
* @this rq.Context
* @param {number} [size=1] The length of each chunk
* @example
* "a" "b" "c" "d" → chunk → ["a"] ["b"] ["c"] ["d"]
* "a" "b" "c" "d" → chunk 2 → ["a", "b"] ["c", "d"]
* "a" "b" "c" "d" → chunk 3 → ["a", "b", "c"] ["d"]
*
* // Edge cases
* "a" "b" "c" "d" → chunk -1 → (empty)
* "a" "b" "c" "d" → chunk 0 → (empty)
*/
function* chunk(size) {
if (size === undefined) {
size = 1;
} else {
size = Math.max(0, _.toInteger(size));
}
if (size > 0) {
var buffer = [];
while (yield* this.pull()) {
buffer.push(this.value);
if (buffer.length >= size) {
yield* this.push(buffer);
buffer = [];
}
}
if (buffer.length > 0) {
yield* this.push(buffer);
}
}
}
/**
* Creates a stream with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are falsey.
*
* @static
* @this rq.Context
* @example
* 0 1 false 2 "" 3 → compact → 1 2 3
*/
function* compact() {
while (yield* this.pull()) {
if (this.value) {
yield* this.push(this.value);
}
}
}
/**
* Creates a new stream concatenating all input arrays.
*
* @static
* @this rq.Context
* @example
* [1] 2 [3] [[4]] → concat → [1, 2, 3, [4]]
*/
function* concat() {
var result = [];
while (yield* this.pull()) {
if (_.isArray(this.value)) {
result.push.apply(result, this.value);
} else {
result.push(this.value);
}
}
yield* this.push(result);
}
/**
* Creates a stream of values not included in the given array
* using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons. The order of result values is determined by the order they occur in
* the input.
*
* @static
* @this rq.Context
* @param {Array} [values] The values to exclude.
* @see without, xor
* @example
* 2 1 → difference [2, 3] → 1
*/
function* difference(values) {
yield* this.spread(_.difference((yield* this.collect()), values));
}
/**
* This method is like `difference` except that it accepts `iteratee` which
* is invoked for each element of the input and `values` to generate the criterion
* by which they're compared. Result values are chosen from the input stream.
* The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to exclude.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* 2.1 1.2 → differenceBy [2.3, 3.4] (Math.floor) → 1.2
* // The `property` iteratee shorthand.
* {"x": 2} {"x": 1} → differenceBy [{"x": 1}] "x" → {"x": 2}
*/
function* differenceBy(values, iteratee) {
yield* this.spread(_.differenceBy((yield* this.collect()), values, iteratee));
}
/**
* This method is like `difference` except that it accepts `comparator`
* which is invoked to compare elements of the input to `values`. The comparator is invoked with
* two arguments: (inputVal, othVal).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to exclude.
* @param {Function} [comparator] The comparator invoked per element.
* @example
* {"x": 1, "y": 2} {"x": 2, "y": 1} → differenceWith [{"x": 1, "y": 2}] (_.isEqual) → {"x": 2, "y": 1}
*/
function* differenceWith(values, comparator) {
yield* this.spread(_.differenceWith((yield* this.collect()), values, comparator));
}
/**
* Creates a slice of the input stream with `n` elements dropped from the beginning.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of elements to drop.
* @example
* 1 2 3 → drop → 2 3
* 1 2 3 → drop 2 → 3
* 1 2 3 → drop 5 → (empty)
* 1 2 3 → drop 0 → 1 2 3
*/
function* drop(n) {
n = n === undefined ? 1 : _.toInteger(n);
while (n > 0 && (yield* this.pull())) {
n -= 1;
}
yield* id.call(this);
}
/**
* Creates a slice of the input stream with `n` elements dropped from the end.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of elements to drop.
* @example
* 1 2 3 → dropRight → 1 2
* 1 2 3 → dropRight 2 → 1
* 1 2 3 → dropRight 5 → (empty)
* 1 2 3 → dropRight 0 → 1 2 3
*/
function* dropRight(n) {
yield* this.spread(_.dropRight((yield* this.collect()), n));
}
/**
* Creates a slice of the input stream excluding elements dropped from the end.
* Elements are dropped until `predicate` returns falsey. The predicate is
* invoked with three arguments: (value, index, array).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @example
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → dropRightWhile (o => !o.a) → {"u": "b", "a": true}
* // The `matches` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → dropRightWhile {"u": "p", "a": false} → {"u": "b", "a": true} {"u": "f", "a": false}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → dropRightWhile ["a", false] → {"u": "b", "a": true}
* // The `property` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → dropRightWhile "a" → {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false}
*/
function* dropRightWhile(predicate) {
yield* this.spread(_.dropRightWhile((yield* this.collect()), predicate));
}
/**
* Creates a slice of the input stream excluding elements dropped from the beginning.
* Elements are dropped until `predicate` returns falsey. The predicate is
* invoked with three arguments: (value, index, array).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → dropWhile (o => !o.a) → {"u": "p", "a": true}
* // The `matches` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → dropWhile {"u": "b", "a": false} → {"u": "f", "a": false} {"u": "p", "a": true}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → dropWhile ["a", false] → {"u": "p", "a": true}
* // The `property` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → dropWhile "a" → {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true}
*/
function* dropWhile(predicate) {
yield* this.spread(_.dropWhile((yield* this.collect()), predicate));
}
/**
* Fills elements of the input stream with `value` from `start` up to, but not
* including, `end`.
*
* @static
* @this rq.Context
* @param {*} value The value to fill the input stream with.
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @example
* 4 6 8 10 → fill "*" 1 3 → 4 "*" "*" 10
*/
function* fill(value, start, end) {
yield* this.spread(_.fill((yield* this.collect()), value, start, end));
}
/**
* This method is like `find` except that it returns the index of the first
* element `predicate` returns truthy for instead of the element itself.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @param {number} [fromIndex=0] The index to search from.
* @example
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → findIndex (o => o.u == 'b') → 0
* // The `matches` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → findIndex {"u": "f", "a": false} → 1
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → findIndex ["a", false] → 0
* // The `property` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → findIndex "a" → 2
*/
function* findIndex(predicate, fromIndex) {
yield* this.push(_.findIndex((yield* this.collect()), predicate, fromIndex));
}
/**
* This method is like `findIndex` except that it iterates over elements
* of `collection` from right to left.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @example
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → findLastIndex (o => o.u == 'p') → 2
* // The `matches` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → findLastIndex {"u": "b", "a": true} → 0
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → findLastIndex ["a", false] → 2
* // The `property` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → findLastIndex "a" → 0
*/
function* findLastIndex(predicate, fromIndex) {
yield* this.push(_.findLastIndex((yield* this.collect()), predicate, fromIndex));
}
/**
* Flattens the input stream a single level deep.
*
* @static
* @this rq.Context
* @example
* 1 [2, [3, [4]], 5] → flatten → 1 2 [3, [4]] 5
*/
function* flatten() {
yield* this.spread(_.flatten((yield* this.collect())));
}
/**
* Recursively flattens the input stream.
*
* @static
* @this rq.Context
* @example
* 1 [2, [3, [4]], 5] → flattenDeep → 1 2 3 4 5
*/
function* flattenDeep() {
yield* this.spread(_.flattenDeep((yield* this.collect())));
}
/**
* Recursively flatten the input stream up to `depth` times.
*
* @static
* @this rq.Context
* @param {number} [depth=1] The maximum recursion depth.
* @example
* 1 [2, [3, [4]], 5] → flattenDepth 1 → 1 2 [3, [4]] 5
* 1 [2, [3, [4]], 5] → flattenDepth 2 → 1 2 3 [4] 5
*/
function* flattenDepth(depth) {
yield* this.spread(_.flattenDepth((yield* this.collect()), depth));
}
/**
* The inverse of `toPairs`; this method returns an object composed
* from key-value `pairs`.
*
* @static
* @this rq.Context
* @example
* ["a", 1] ["b", 2] → fromPairs → {"a": 1, "b": 2}
*/
function* fromPairs() {
yield* this.push(_.fromPairs((yield* this.collect())));
}
/**
* Gets the first element of the input stream.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → head → 1
* (empty) → head → null
*/
function* head() {
yield* this.push(_.head((yield* this.collect())));
}
/**
* Gets the index at which the first occurrence of `value` is found in the input stream
* using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons. If `fromIndex` is negative, it's used as the
* offset from the end of the input stream.
*
* @static
* @this rq.Context
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @example
* 1 2 1 2 → indexOf 2 → 1
* // Search from the `fromIndex`.
* 1 2 1 2 → indexOf 2 2 → 3
*/
function* indexOf(value, fromIndex) {
yield* this.push(_.indexOf((yield* this.collect()), value, fromIndex));
}
/**
* Gets all but the last element of the input stream.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → initial → 1 2
*/
function* initial() {
yield* this.spread(_.initial((yield* this.collect())));
}
/**
* Creates a stream of unique values that are included in the given array
* using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons. The order of result values is determined by the
* order they occur in the input stream.
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @example
* 2 1 → intersection [2, 3] → 2
*/
function* intersection(values) {
yield* this.spread(_.intersection((yield* this.collect()), values));
}
/**
* This method is like `intersection` except that it accepts `iteratee`
* which is invoked for each element in `values` to generate the criterion
* by which they're compared. Result values are chosen from the input stream.
* The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* 2.1 1.2 → intersectionBy [2.3, 3.4] (Math.floor) → 2.1
* // The `property` iteratee shorthand.
* {"x": 1} → intersectionBy [{"x": 2}, {"x": 1}] "x" → {"x": 1}
*/
function* intersectionBy(values, iteratee) {
yield* this.spread(_.intersectionBy((yield* this.collect()), values, iteratee));
}
/**
* This method is like `intersection` except that it accepts `comparator`
* which is invoked to compare elements of `values`. Result values are chosen
* from the input stream. The comparator is invoked with two arguments:
* (arrVal, othVal).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @example
* {"x": 1, "y": 2} {"x": 2, "y": 1} → intersectionWith [{"x": 1, "y": 1}, {"x": 1, "y": 2}] (_.isEqual) → {"x": 1, "y": 2}
*/
function* intersectionWith(values, comparator) {
yield* this.spread(_.intersectionWith((yield* this.collect()), values, comparator));
}
/**
* Converts all elements in the input stream into a string separated by `separator`.
*
* @static
* @this rq.Context
* @param {string} [separator=','] The element separator.
* @example
* "a" "b" "c" → join → "a,b,c"
* "a" "b" "c" → join "~" → "a~b~c"
*/
function* join(separator) {
yield* this.push(_.join((yield* this.collect()), separator));
}
/**
* Gets the last element of the input stream.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → last → 3
*/
function* last() {
yield* this.push(_.last((yield* this.collect())));
}
/**
* This method is like `indexOf` except that it iterates over elements of
* the input stream from right to left.
*
* @static
* @this rq.Context
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @example
* 1 2 1 2 → lastIndexOf 2 → 3
* 1 2 1 2 → lastIndexOf 2 2 → 1
*/
function* lastIndexOf(value, fromIndex) {
yield* this.push(_.lastIndexOf((yield* this.collect()), value, fromIndex));
}
/**
* Gets the element at index `n` of the input stream. If `n` is negative, the nth
* element from the end is returned.
*
* @static
* @this rq.Context
* @param {number} [n=0] The index of the element to return.
* @example
* "a" "b" "c" "d" → nth 1 → "b"
* "a" "b" "c" "d" → nth -2 → "c"
*/
function* nth(n) {
yield* this.push(_.nth((yield* this.collect()), n));
}
// pull, pullAll, pullAllBy, pullAllWith, pullAt, remove don't make sense
/**
* Reverses the input stream so that the first element becomes the last, the second
* element becomes the second to last, and so on.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → reverse → 3 2 1
*/
function* reverse() {
yield* this.spread(_.reverse((yield* this.collect())));
}
/**
* Creates a slice of the input stream from `start` up to, but not including, `end`.
*
* @static
* @this rq.Context
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @example
* 1 2 3 4 → slice 1 3 → 2 3
*/
function* slice(start, end) {
yield* this.spread(_.slice((yield* this.collect()), start, end));
}
/**
* Uses a binary search to determine the lowest index at which `value`
* should be inserted into the input stream in order to maintain its sort order.
*
* @static
* @this rq.Context
* @param {*} value The value to evaluate.
* into the input stream.
* @example
* 30 50 → sortedIndex 40 → 1
*/
function* sortedIndex(value) {
yield* this.push(_.sortedIndex((yield* this.collect()), value));
}
/**
* This method is like `sortedIndex` except that it accepts `iteratee`
* which is invoked for `value` and each element of the input stream to compute their
* sort ranking. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {*} value The value to evaluate.
* @param {Function} [iteratee=_.identity]
* The iteratee invoked per element.
* into the input stream.
* @example
* {"x": 4} {"x": 5} → sortedIndexBy {"x": 4} (o => o.x) → 0
* // The `property` iteratee shorthand.
* {"x": 4} {"x": 5} → sortedIndexBy {"x": 4} "x" → 0
*/
function* sortedIndexBy(value, iteratee) {
yield* this.push(_.sortedIndexBy((yield* this.collect()), value, iteratee));
}
/**
* This method is like `indexOf` except that it performs a binary
* search on a sorted the input stream.
*
* @static
* @this rq.Context
* @param {*} value The value to search for.
* @example
* 4 5 5 5 6 → sortedIndexOf 5 → 1
*/
function* sortedIndexOf(value) {
yield* this.push(_.sortedIndexOf((yield* this.collect()), value));
}
/**
* This method is like `sortedIndex` except that it returns the highest
* index at which `value` should be inserted into the input stream in order to
* maintain its sort order.
*
* @static
* @this rq.Context
* @param {*} value The value to evaluate.
* into the input stream.
* @example
* 4 5 5 5 6 → sortedLastIndex 5 → 4
*/
function* sortedLastIndex(value) {
yield* this.push(_.sortedLastIndex((yield* this.collect()), value));
}
/**
* This method is like `sortedLastIndex` except that it accepts `iteratee`
* which is invoked for `value` and each element of the input stream to compute their
* sort ranking. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {*} value The value to evaluate.
* @param {Function} [iteratee=_.identity]
* The iteratee invoked per element.
* into the input stream.
* @example
* {"x": 4} {"x": 5} → sortedLastIndexBy {"x": 4} (o => o.x) → 1
* // The `property` iteratee shorthand.
* {"x": 4} {"x": 5} → sortedLastIndexBy {"x": 4} "x" → 1
*/
function* sortedLastIndexBy(value, iteratee) {
yield* this.push(_.sortedLastIndexBy((yield* this.collect()), value, iteratee));
}
/**
* This method is like `lastIndexOf` except that it performs a binary
* search on a sorted the input stream.
*
* @static
* @this rq.Context
* @param {*} value The value to search for.
* @example
* 4 5 5 5 6 → sortedLastIndexOf 5 → 3
*/
function* sortedLastIndexOf(value) {
yield* this.push(_.sortedLastIndexOf((yield* this.collect()), value));
}
/**
* This method is like `uniq` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @this rq.Context
* @example
* 1 1 2 → sortedUniq → 1 2
*/
function* sortedUniq() {
yield* this.spread(_.sortedUniq((yield* this.collect())));
}
/**
* This method is like `uniqBy` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @this rq.Context
* @param {Function} [iteratee] The iteratee invoked per element.
* @example
* 1.1 1.2 2.3 2.4 → sortedUniqBy (Math.floor) → 1.1 2.3
*/
function* sortedUniqBy(iteratee) {
yield* this.spread(_.sortedUniqBy((yield* this.collect()), iteratee));
}
/**
* Gets all but the first element of the input stream.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → tail → 2 3
*/
function* tail() {
yield* this.spread(_.tail((yield* this.collect())));
}
/**
* Creates a slice of the input stream with `n` elements taken from the beginning.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of elements to take.
* @example
* 1 2 3 → take → 1
* 1 2 3 → take 2 → 1 2
* 1 2 3 → take 5 → 1 2 3
* 1 2 3 → take 0 → (empty)
*/
function* take(n) {
yield* this.spread(_.take((yield* this.collect()), n));
}
/**
* Creates a slice of the input stream with `n` elements taken from the end.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of elements to take.
* @example
* 1 2 3 → takeRight → 3
* 1 2 3 → takeRight 2 → 2 3
* 1 2 3 → takeRight 5 → 1 2 3
* 1 2 3 → takeRight 0 → (empty)
*/
function* takeRight(n) {
yield* this.spread(_.takeRight((yield* this.collect()), n));
}
/**
* Creates a slice of the input stream with elements taken from the end. Elements are
* taken until `predicate` returns falsey. The predicate is invoked with
* three arguments: (value, index, array).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → takeRightWhile (o => !o.a) → {"u": "f", "a": false} {"u": "p", "a": false}
* // The `matches` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → takeRightWhile {"u": "p", "a": false} → {"u": "p", "a": false}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → takeRightWhile ["a", false] → {"u": "f", "a": false} {"u": "p", "a": false}
* // The `property` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} {"u": "p", "a": false} → takeRightWhile "a" → (empty)
*/
function* takeRightWhile(predicate) {
yield* this.spread(_.takeRightWhile((yield* this.collect()), predicate));
}
/**
* Creates a slice of the input stream with elements taken from the beginning. Elements
* are taken until `predicate` returns falsey. The predicate is invoked with
* three arguments: (value, index, array).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → takeWhile (o => !o.a) → {"u": "b", "a": false} {"u": "f", "a": false}
* // The `matches` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → takeWhile {"u": "b", "a": false} → {"u": "b", "a": false}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → takeWhile ["a", false] → {"u": "b", "a": false} {"u": "f", "a": false}
* // The `property` iteratee shorthand.
* {"u": "b", "a": false} {"u": "f", "a": false} {"u": "p", "a": true} → takeWhile "a" → (empty)
*/
function* takeWhile(predicate) {
yield* this.spread(_.takeWhile((yield* this.collect()), predicate));
}
/**
* Creates a stream of unique values, in order, from all given values using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @example
* 2 → union [1, 2] → 2 1
*/
function* union(values) {
yield* this.spread(_.union((yield* this.collect()), values));
}
/**
* This method is like `union` except that it accepts `iteratee` which is
* invoked for each element of `values` to generate the criterion by
* which uniqueness is computed. Result values are chosen from the input stream.
* The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @param {Function} [iteratee=_.identity]
* The iteratee invoked per element.
* @example
* 2.1 → unionBy [1.2, 2.3] (Math.floor) → 2.1 1.2
* // The `property` iteratee shorthand.
* {"x": 1} → unionBy [{"x": 2}, {"x": 1}] "x" → {"x": 1} {"x": 2}
*/
function* unionBy(values, iteratee) {
yield* this.spread(_.unionBy((yield* this.collect()), values, iteratee));
}
/**
* This method is like `union` except that it accepts `comparator` which
* is invoked to compare elements of `values`. Result values are chosen from
* the input stream. The comparator is invoked with two arguments: (arrVal, othVal).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @example
* {"x": 1, "y": 2} {"x": 2, "y": 1} → unionWith [{"x": 1, "y": 1}, {"x": 1, "y": 2}] (_.isEqual) → {"x": 1, "y": 2} {"x": 2, "y": 1} {"x": 1, "y": 1}
*/
function* unionWith(values, comparator) {
yield* this.spread(_.unionWith((yield* this.collect()), values, comparator));
}
/**
* Creates a duplicate-free version of the input stream, using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons, in which only the first occurrence of each
* element is kept.
*
* @static
* @this rq.Context
* @example
* 2 1 2 → uniq → 2 1
*/
function* uniq() {
yield* this.spread(_.uniq((yield* this.collect())));
}
/**
* This method is like `uniq` except that it accepts `iteratee` which is
* invoked for each element in the input stream to generate the criterion by which
* uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The iteratee invoked per element.
* @example
* 2.1 1.2 2.3 → uniqBy (Math.floor) → 2.1 1.2
* // The `property` iteratee shorthand.
* {"x": 1} {"x": 2} {"x": 1} → uniqBy "x" → {"x": 1} {"x": 2}
*/
function* uniqBy(iteratee) {
yield* this.spread(_.uniqBy((yield* this.collect()), iteratee));
}
/**
* This method is like `uniq` except that it accepts `comparator` which
* is invoked to compare elements of the input stream. The comparator is invoked with
* two arguments: (arrVal, othVal).
*
* @static
* @this rq.Context
* @param {Function} [comparator] The comparator invoked per element.
* @example
* {"x": 1, "y": 2} {"x": 2, "y": 1} {"x": 1, "y": 2} → uniqWith (_.isEqual) → {"x": 1, "y": 2} {"x": 2, "y": 1}
*/
function* uniqWith(comparator) {
yield* this.spread(_.uniqWith((yield* this.collect()), comparator));
}
/**
* This method is like `zip` except that it accepts a stream of grouped
* elements and creates an array regrouping the elements to their pre-zip
* configuration.
*
* @static
* @this rq.Context
* @example
* ["a", 1, true] ["b", 2, false] → unzip → ["a", "b"] [1, 2] [true, false]
*/
function* unzip() {
yield* this.spread(_.unzip((yield* this.collect())));
}
/**
* This method is like `unzip` except that it accepts `iteratee` to specify
* how regrouped values should be combined. The iteratee is invoked with the
* elements of each group: (...group).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function to combine
* regrouped values.
* @example
* [1, 10, 100] [2, 20, 200] → unzipWith (_.add) → 3 30 300
*/
function* unzipWith(iteratee) {
yield* this.spread(_.unzipWith((yield* this.collect()), iteratee));
}
/**
* Creates a stream excluding all given values using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
* @this rq.Context
* @param {...*} [values] The values to exclude.
* @see _.difference, _.xor
* @example
* 2 1 2 3 → without 1 2 → 3
*/
function* without(values) {
var args = Array.prototype.slice.call(arguments);
args.unshift((yield* this.collect()));
yield* this.spread(_.without.apply(null, args));
}
/**
* Creates a stream of unique values that is the
* [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
* of the given values. The order of result values is determined by the order
* they occur in the input stream.
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @see _.difference, _.without
* @example
* 2 1 → xor [2, 3] → 1 3
*/
function* xor(values) {
yield* this.spread(_.xor((yield* this.collect()), values));
}
/**
* This method is like `xor` except that it accepts `iteratee` which is
* invoked for each element of each `values` to generate the criterion by
* which by which they're compared. The iteratee is invoked with one argument:
* (value).
*
* @static
* @this rq.Context
* @param {Array} [values] The arrays to inspect.
* @param {Function} [iteratee=_.identity]
* The iteratee invoked per element.
* @example
* 2.1 1.2 → xorBy [2.3, 3.4] (Math.floor) → 1.2 3.4
* // The `property` iteratee shorthand.
* {"x": 1} → xorBy [{"x": 2}, {"x": 1}] "x" → {"x": 2}
*/
function* xorBy(values, iteratee) {
yield* this.spread(_.xorBy((yield* this.collect()), values, iteratee));
}
/**
* This method is like `xor` except that it accepts `comparator` which is
* invoked to compare elements of `values`. The comparator is invoked with
* two arguments: (arrVal, othVal).
*
* @static
* @this rq.Context
* @param {Array} [values] The values to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @example
* {"x": 1, "y": 2} {"x": 2, "y": 1} → xorWith [{"x": 1, "y": 1}, {"x": 1, "y": 2}] (_.isEqual) → {"x": 2, "y": 1} {"x": 1, "y": 1}
*/
function* xorWith(values, comparator) {
yield* this.spread(_.xorWith((yield* this.collect()), values, comparator));
}
/**
* Creates a stream of grouped elements, the first of which contains the
* first elements of the given arrays, the second of which contains the
* second elements of the given arrays, and so on.
*
* @static
* @this rq.Context
* @example
* ["a", "b"] [1, 2] [true, false] → zip → ["a", 1, true] ["b", 2, false]
*/
function* zip() {
yield* this.spread(_.zip.apply(null, (yield* this.collect())));
}
// zipObject and zipObjectDeep don't make sense
/**
* This method is like `zip` except that it accepts `iteratee` to specify
* how grouped values should be combined. The iteratee is invoked with the
* elements of each group: (...group).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function to combine grouped values.
* @example
*
* [1, 2] [10, 20] [100, 200] → zipWith (a, b, c)=>{a + b + c} → 111 222
*/
function* zipWith(iteratee) {
var args = [];
while (yield* this.pull()) {
args.push(this.value);
}
args.push(iteratee);
yield* this.spread(_.zipWith.apply(null, args));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Collection ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks if `predicate` returns truthy for **all** elements of the input stream.
* Iteration is stopped once `predicate` returns falsey. The predicate is
* invoked with two arguments: (value, index).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* true 1 null "yes" → every (Boolean) → false
* // With index
* 1 2 3 → every (x, i) => { i + 1 == x } → true
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → every {"u": "b", "a": false} → false
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → every ["a", false] → true
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": false} → every "a" → false
*/
function* every(predicate) {
predicate = _.iteratee(predicate);
var i = 0;
while (yield* this.pull()) {
if (!predicate(this.value, i)) {
yield* this.push(false);
return;
}
i++;
}
yield* this.push(true);
}
/**
* Creates an object composed of keys generated from the results of running
* each element of the input stream thru `iteratee`. The corresponding value of
* each key is the number of times the key was returned by `iteratee`. The
* iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The iteratee to transform keys.
* @example
*
* 6.1 4.2 6.3 → countBy (Math.floor) → {"4": 1, "6": 2}
* "one" "two" "three" → countBy "length" → {"3": 2, "5": 1}
*/
function* countBy(iteratee) {
yield* this.push(_.countBy((yield* this.collect()), iteratee));
}
/**
* Iterates over elements of the input stream, returning an array of all elements
* `predicate` returns truthy for. The predicate is invoked with two
* arguments: (value, index).
*
* **Note:** Unlike `remove`, this method returns a new array.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @see _.reject
* @example
* "a" "b" "c" → filter (s)=>{"a" === s} → "a"
* "a" "ab" "abc" → filter (s)=>{s.length == 2} → "ab"
* "a" "ab" "abc" → filter (s, i)=>{i % 2 == 0} → "a" "abc"
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} → filter (o)=>{!o.a} → {"u": "f", "g": 40, "a": false}
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} → filter {"g": 36, "a": true} → {"u": "b", "g": 36, "a": true}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} → filter ["a", false] → {"u": "f", "g": 40, "a": false}
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} → filter "a" → {"u": "b", "g": 36, "a": true}
*/
function* filter(predicate) {
predicate = _.iteratee(predicate);
var i = 0;
while (yield* this.pull()) {
if (predicate(this.value, i)) {
yield* this.push(this.value);
}
i++;
}
}
/**
* Iterates over elements of the input stream, returning the first element
* `predicate` returns truthy for. The predicate is invoked with two
* arguments: (value, index).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @example
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} {"u": "p", "g": 1, "a": true} → find (o)=>{o.g < 40} → {"u": "b", "g": 36, "a": true}
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} {"u": "p", "g": 1, "a": true} → find {"g": 1, "a": true} → {"u": "p", "g": 1, "a": true}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} {"u": "p", "g": 1, "a": true} → find ["a", false] → {"u": "f", "g": 40, "a": false}
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": true} {"u": "f", "g": 40, "a": false} {"u": "p", "g": 1, "a": true} → find "a" → {"u": "b", "g": 36, "a": true}
*/
function* find(predicate) {
predicate = _.iteratee(predicate);
var i = 0;
while (yield* this.pull()) {
if (predicate(this.value, i)) {
yield* this.push(this.value);
return;
}
i++;
}
}
/**
* This method is like `find` except that it iterates over elements of
* the input stream from right to left.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity]
* The function invoked per iteration.
* @param {number} [fromIndex=collection.length-1] The index to search from.
* @example
* 1 2 3 4 → findLast (n)=>{n % 2 == 1} → 3
*/
function* findLast(predicate, fromIndex) {
yield* this.push(_.findLast((yield* this.collect()), predicate, fromIndex));
}
/**
* Creates a flattened array of values by running each element in the input stream
* thru `iteratee` and flattening the mapped results. The iteratee is invoked
* with three arguments: (value, index|key, collection).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The function invoked per iteration.
* @example
* 1 2 → flatMap (n)=>{[n, n]} → 1 1 2 2
*/
function* flatMap(iteratee) {
yield* this.spread(_.flatMap((yield* this.collect()), iteratee));
}
/**
* This method is like `flatMap` except that it recursively flattens the
* mapped results.
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The function invoked per iteration.
* @example
* 1 2 → flatMapDeep (n)=>{[[[n, n]]]} → 1 1 2 2
*/
function* flatMapDeep(iteratee) {
yield* this.spread(_.flatMapDeep((yield* this.collect()), iteratee));
}
/**
* This method is like `flatMap` except that it recursively flattens the
* mapped results up to `depth` times.
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The function invoked per iteration.
* @param {number} [depth=1] The maximum recursion depth.
* @example
* 1 2 → flatMapDepth (n)=>{[[[n, n]]]} 2 → [1, 1] [2, 2]
*/
function* flatMapDepth(iteratee, depth) {
yield* this.spread(_.flatMapDepth((yield* this.collect()), iteratee, depth));
}
// forEach and forEachRight make no sense
/**
* Creates an object composed of keys generated from the results of running
* each element of the input stream thru `iteratee`. The order of grouped values
* is determined by the order they occur in the input stream. The corresponding
* value of each key is an array of elements responsible for generating the
* key. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The iteratee to transform keys.
* @example
*
* 6.1 4.2 6.3 → groupBy (Math.floor) → {"4": [4.2], "6": [6.1, 6.3]}
* // The `property` iteratee shorthand.
* "one" "two" "three" → groupBy "length" → {"3": ["one", "two"], "5": ["three"]}
*/
function* groupBy(iteratee) {
yield* this.push(_.groupBy((yield* this.collect()), iteratee));
}
/**
* Checks if `value` is in the input stream. If the input stream is a string, it's
* checked for a substring of `value`, otherwise
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* is used for equality comparisons. If `fromIndex` is negative, it's used as
* the offset from the end of the input stream.
*
* @static
* @this rq.Context
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @example
*
* 1 2 3 → includes 1 → true
* 1 2 3 → includes 1 2 → false
*/
function* includes(value, fromIndex) {
yield* this.push(_.includes((yield* this.collect()), value, fromIndex));
}
/**
* Invokes the method at `path` of each element in the input stream, returning
* an array of the results of each invoked method. Any additional arguments
* are provided to each invoked method. If `path` is a function, it's invoked
* for, and `this` bound to, each element in the input stream.
*
* @static
* @this rq.Context
* @param {Array|Function|string} path The path of the method to invoke or
* the function invoked per iteration.
* @param {...*} [args] The arguments to invoke each method with.
* @example
* [5, 1, 7] [3, 2, 1] → invokeMap "sort" → [1, 5, 7] [1, 2, 3]
* "123" "456" → invokeMap "split" "" → ["1", "2", "3"] ["4", "5", "6"]
*/
function* invokeMap(path, args) {
var fullArgs = Array.prototype.slice.call(arguments);
fullArgs.unshift((yield* this.collect()));
yield* this.spread(_.invokeMap.apply(null, fullArgs));
}
/**
* Creates an object composed of keys generated from the results of running
* each element of the input stream thru `iteratee`. The corresponding value of
* each key is the last element responsible for generating the key. The
* iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity]
* The iteratee to transform keys.
* @example
* {"dir": "left", "code": 97} {"dir": "right", "code": 100} → keyBy (o)=>{String.fromCharCode(o.code)} → {"a": {"dir": "left", "code": 97}, "d": {"dir": "right", "code": 100}}
* {"dir": "left", "code": 97} {"dir": "right", "code": 100} → keyBy "dir" → {"left": {"dir": "left", "code": 97}, "right": {"dir": "right", "code": 100}}
*/
function* keyBy(iteratee) {
yield* this.push(_.keyBy((yield* this.collect()), iteratee));
}
/**
* Creates a stream of values by running each element in the input stream thru
* `iteratee`. The iteratee is invoked with two arguments:
* (value, index).
*
* Many lodash methods are guarded to work as iteratees for methods like
* `every`, `filter`, `map`, `mapValues`, `reject`, and `some`.
*
* The guarded methods are:
* `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
* `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
* `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
* `template`, `trim`, `trimEnd`, `trimStart`, and `words`
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @example
* 4 8 → map (x)=>{x*x} → 16 64
* // With index
* 4 8 → map (x, i)=>{x + i} → 4 9
* // The `property` iteratee shorthand.
* {"u": "b"} {"u": "f"} → map "u" → "b" "f"
*/
function* map(iteratee) {
iteratee = _.iteratee(iteratee);
var i = 0;
while (yield* this.pull()) {
yield* this.push(iteratee(this.value, i));
i++;
}
}
/**
* This method is like `sortBy` except that it allows specifying the sort
* orders of the iteratees to sort by. If `orders` is unspecified, all values
* are sorted in ascending order. Otherwise, specify an order of "desc" for
* descending or "asc" for ascending sort order of corresponding values.
*
* @static
* @this rq.Context
* @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
* The iteratees to sort by.
* @param {string[]} [orders] The sort orders of `iteratees`.
* @example
* {"u": "f", "g": 48} {"u": "b", "g": 34} {"u": "f", "g": 40} {"u": "b", "g": 36} → orderBy ["u", "g"] ["asc", "desc"] → {"u": "b", "g": 36} {"u": "b", "g": 34} {"u": "f", "g": 48} {"u": "f", "g": 40}
*/
function* orderBy(iteratees, orders) {
yield* this.spread(_.orderBy((yield* this.collect()), iteratees, orders));
}
/**
* Creates a stream of elements split into two groups, the first of which
* contains elements `predicate` returns truthy for, the second of which
* contains elements `predicate` returns falsey for. The predicate is
* invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @example
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} {"u": "p", "g": 1, "a": false} → partition (o)=>{o.a} → [{"u": "f", "g": 40, "a": true}] [{"u": "b", "g": 36, "a": false}, {"u": "p", "g": 1, "a": false}]
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} {"u": "p", "g": 1, "a": false} → partition {"g": 1, "a": false} → [{"u": "p", "g": 1, "a": false}] [{"u": "b", "g": 36, "a": false}, {"u": "f", "g": 40, "a": true}]
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} {"u": "p", "g": 1, "a": false} → partition ["a", false] → [{"u": "b", "g": 36, "a": false}, {"u": "p", "g": 1, "a": false}] [{"u": "f", "g": 40, "a": true}]
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} {"u": "p", "g": 1, "a": false} → partition "a" → [{"u": "f", "g": 40, "a": true}] [{"u": "b", "g": 36, "a": false}, {"u": "p", "g": 1, "a": false}]
*/
function* partition(predicate) {
yield* this.spread(_.partition((yield* this.collect()), predicate));
}
/**
* Reduces the input stream to a value which is the accumulated result of running
* each element in the input stream thru `iteratee`, where each successive
* invocation is supplied the return value of the previous. If `accumulator`
* is not given, the first element of the input stream is used as the initial
* value. The iteratee is invoked with four arguments:
* (accumulator, value, index|key, collection).
*
* Many lodash methods are guarded to work as iteratees for methods like
* `reduce`, `reduceRight`, and `transform`.
*
* The guarded methods are:
* `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
* and `sortBy`
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @see _.reduceRight
* @example
* 1 2 → reduce (sum, n)=>{sum + n} 0 → 3
*/
function* reduce(iteratee, accumulator) {
yield* this.push(_.reduce((yield* this.collect()), iteratee, accumulator));
}
/**
* This method is like `reduce` except that it iterates over elements of
* the input stream from right to left.
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @see _.reduce
* @example
* [0, 1] [2, 3] [4, 5] → reduceRight (flattened, other)=>{flattened.concat(other)} [] → [4, 5, 2, 3, 0, 1]
*/
function* reduceRight(iteratee, accumulator) {
yield* this.push(_.reduceRight((yield* this.collect()), iteratee, accumulator));
}
/**
* The opposite of `filter`; this method returns the elements of the input stream
* that `predicate` does **not** return truthy for.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @see _.filter
* @example
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} → reject (o)=>{!o.a} → {"u": "f", "g": 40, "a": true}
* // The `matches` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} → reject {"g": 40, "a": true} → {"u": "b", "g": 36, "a": false}
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} → reject ["a", false] → {"u": "f", "g": 40, "a": true}
* // The `property` iteratee shorthand.
* {"u": "b", "g": 36, "a": false} {"u": "f", "g": 40, "a": true} → reject "a" → {"u": "b", "g": 36, "a": false}
*/
function* reject(predicate) {
predicate = _.iteratee(predicate);
var i = 0;
while (yield* this.pull()) {
if (!predicate(this.value, i)) {
yield* this.push(this.value);
}
i++;
}
}
/**
* Gets a random element from the input stream.
*
* @static
* @this rq.Context
* @example
* 1 2 3 4 → sample → 2 (not tested)
*/
function* sample() {
yield* this.push(_.sample((yield* this.collect())));
}
/**
* Gets `n` random elements at unique keys from the input stream up to the
* size of the input stream.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of elements to sample.
* @example
* 1 2 3 → sampleSize 2 → 3 1 (not tested)
* 1 2 3 → sampleSize 4 → 2 3 1 (not tested)
*/
function* sampleSize(n) {
yield* this.push(_.sampleSize((yield* this.collect()), n));
}
/**
* Creates a stream of shuffled values, using a version of the
* [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
*
* @static
* @this rq.Context
* @example
* 1 2 3 4 → shuffle → 4 1 3 2 (not tested)
*/
function* shuffle() {
yield* this.spread(_.shuffle((yield* this.collect())));
}
/**
* Gets the size of the input stream by returning its length.
*
* @static
* @this rq.Context
* @example
* 1 2 3 → size → 3
*/
function* size() {
yield* this.push(_.size((yield* this.collect())));
}
/**
* Checks if `predicate` returns truthy for **any** element of the input stream.
* Iteration is stopped once `predicate` returns truthy. The predicate is
* invoked with two arguments: (value, index).
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @example
* null 0 "yes" false → some (x)=>{Boolean(x)} → true
* // With index
* 5 1 8 → some (x, i) => { i == x } → true
* // The `matches` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → some {"u": "b", "a": false} → false
* // The `matchesProperty` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → some ["a", false] → true
* // The `property` iteratee shorthand.
* {"u": "b", "a": true} {"u": "f", "a": false} → some "a" → true
*/
function* some(predicate) {
predicate = _.iteratee(predicate);
var i = 0;
while (yield* this.pull()) {
if (predicate(this.value, i)) {
yield* this.push(true);
return;
}
i++;
}
yield* this.push(false);
}
/**
* Creates a stream of elements, sorted in ascending order by the results of
* running each element in a collection thru each iteratee. This method
* performs a stable sort, that is, it preserves the original sort order of
* equal elements. The iteratees are invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {...(Function|Function[])} [iteratees=[_.identity]]
* The iteratees to sort by.
* @example
* {"u": "f", "g": 48} {"u": "b", "g": 36} {"u": "f", "g": 40} {"u": "b", "g": 34} → sortBy (o)=>{o.u} → {"u": "b", "g": 36} {"u": "b", "g": 34} {"u": "f", "g": 48} {"u": "f", "g": 40}
* {"u": "f", "g": 48} {"u": "b", "g": 36} {"u": "f", "g": 40} {"u": "b", "g": 34} → sortBy ["u", "g"] → {"u": "b", "g": 34} {"u": "b", "g": 36} {"u": "f", "g": 40} {"u": "f", "g": 48}
* {"u": "f", "g": 48} {"u": "b", "g": 36} {"u": "f", "g": 40} {"u": "b", "g": 34} → sortBy "u" (o)=>{o.a/10} → {"u": "b", "g": 36} {"u": "b", "g": 34} {"u": "f", "g": 48} {"u": "f", "g": 40}
*/
function* sortBy(iteratees) {
yield* this.spread(_.orderBy((yield* this.collect()), iteratees));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Date ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @this rq.Context
* @example
* (empty) → now → 1470104632000 (not tested)
*/
function* now() {
while (true) {
yield* this.push(_.now());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Lang ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
// castArray, clone, cloneDeep, cloneDeepWith, cloneWith don't make sense
/**
* Checks if input objects conform to `source` by invoking the predicate
* properties of `source` with the corresponding property values of each
* input object.
*
* **Note:** This method is equivalent to `conforms` when `source` is
* partially applied.
*
* @static
* @this rq.Context
* @param {Object} source The object of property predicates to conform to.
* @example
* {"a": 1, "b": 2 } → conformsTo {"b": (n)=>{ n > 1 } } → true (not tested)
* {"a": 1, "b": 2 } → conformsTo {"b": (n)=>{ n > 2 } } → false (not tested)
*/
function* conformsTo(source) {
while (yield* this.pull()) {
yield* this.push(_.conformsTo(this.value, source));
}
}
/**
* Performs a
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* comparison between two values to determine if they are equivalent.
*
* @static
* @this rq.Context
* @param {*} other The other value to compare.
* @example
* 2 3 → eq 2 → true false
* "a" "b" → eq "a" → true false
* {} → eq {} → false
*/
function* eq(other) {
while (yield* this.pull()) {
yield* this.push(_.eq(this.value, other));
}
}
/**
* Checks if each input value is greater than `other`.
*
* @static
* @this rq.Context
* @param {*} other The other value to compare.
* @example
* 1 2 3 → gt 2 → false false true
*/
function* gt(other) {
while (yield* this.pull()) {
yield* this.push(_.gt(this.value, other));
}
}
/**
* Checks if each input value is greater than or equal to `other`.
*
* @static
* @this rq.Context
* @param {*} other The other value to compare.
* @example
* 1 2 3 → gte 2 → false true true
*/
function* gte(other) {
while (yield* this.pull()) {
yield* this.push(_.gte(this.value, other));
}
}
// isArguments doesn't make sense
/**
* Checks if each input value is classified as an `Array` object.
*
* @static
* @this rq.Context
* @example
* [1, 2, 3] "abc" true {"length": 2} → isArray → true false false false
*/
function* isArray() {
while (yield* this.pull()) {
yield* this.push(_.isArray(this.value));
}
}
/**
* Checks if each input value is classified as an `ArrayBuffer` object.
*
* @static
* @this rq.Context
*/
function* isArrayBuffer() {
while (yield* this.pull()) {
yield* this.push(_.isArrayBuffer(this.value));
}
}
/**
* Checks if each input value is array-like. A value is considered array-like if it's
* not a function and has a `value.length` that's an integer greater than or
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
*
* @static
* @this rq.Context
* @example
* [1, 2, 3] "abc" true {"length": 2} → isArrayLike → true true false true
*/
function* isArrayLike() {
while (yield* this.pull()) {
yield* this.push(_.isArrayLike(this.value));
}
}
/**
* This method is like `isArrayLike` except that it also checks if `value`
* is an object.
*
* @static
* @this rq.Context
* @example
* [1, 2, 3] "abc" true {"length": 2} → isArrayLikeObject → true false false true
*/
function* isArrayLikeObject() {
while (yield* this.pull()) {
yield* this.push(_.isArrayLikeObject(this.value));
}
}
/**
* Checks if each input value is classified as a boolean primitive or object.
*
* @static
* @this rq.Context
* @example
* false null → isBoolean → true false
*/
function* isBoolean() {
while (yield* this.pull()) {
yield* this.push(_.isBoolean(this.value));
}
}
/**
* Checks if each input value is a buffer.
*
* @static
* @this rq.Context
*/
function* isBuffer() {
while (yield* this.pull()) {
yield* this.push(_.isBuffer(this.value));
}
}
/**
* Checks if each input value is classified as a `Date` object.
*
* @static
* @this rq.Context
*/
function* isDate() {
while (yield* this.pull()) {
yield* this.push(_.isDate(this.value));
}
}
// isElement doesn't make sense
/**
* Checks if `value` is an empty object, collection, map, or set.
*
* Objects are considered empty if they have no own enumerable string keyed
* properties.
*
* Array-like values such as `arguments` objects, arrays, buffers, strings, or
* jQuery-like collections are considered empty if they have a `length` of `0`.
* Similarly, maps and sets are considered empty if they have a `size` of `0`.
*
* @static
* @this rq.Context
* @example
* null true 1 [1, 2, 3] {"a": 1} → isEmpty → true true true false false
*/
function* isEmpty() {
while (yield* this.pull()) {
yield* this.push(_.isEmpty(this.value));
}
}
/**
* Performs a deep comparison between two values to determine if they are
* equivalent.
*
* **Note:** This method supports comparing arrays, array buffers, booleans,
* date objects, error objects, maps, numbers, `Object` objects, regexes,
* sets, strings, symbols, and typed arrays. `Object` objects are compared
* by their own, not inherited, enumerable properties. Functions and DOM
* nodes are **not** supported.
*
* @static
* @this rq.Context
* @param {*} other The other value to compare.
* @example
* {"a": 1} 2 {"a": 2} → isEqual {"a": 1} → true false false
*/
function* isEqual(other) {
while (yield* this.pull()) {
yield* this.push(_.isEqual(this.value, other));
}
}
/**
* This method is like `isEqual` except that it accepts `customizer` which
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
* are handled by the method instead. The `customizer` is invoked with up to
* six arguments: (objValue, othValue [, index|key, object, other, stack]).
*
* @static
* @this rq.Context
* @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparisons.
* @example
* 1.2 2.1 3.2 → isEqualWith 1.2 (x, y)=>{Math.floor(x) == Math.ceil(y)} → true false false
*/
function* isEqualWith(other, customizer) {
while (yield* this.pull()) {
yield* this.push(_.isEqual(this.value, other, customizer));
}
}
// isError doesn't make sense
function* isFinite(other) {
while (yield* this.pull()) {
yield* this.push(_.isFinite(this.value));
}
}
function* isFunction() {
while (yield* this.pull()) {
yield* this.push(_.isFunction(this.value));
}
}
function* isInteger() {
while (yield* this.pull()) {
yield* this.push(_.isInteger(this.value));
}
}
function* isLength() {
while (yield* this.pull()) {
yield* this.push(_.isLength(this.value));
}
}
function* isMap() {
while (yield* this.pull()) {
yield* this.push(_.isMap(this.value));
}
}
function* isMatch(source) {
while (yield* this.pull()) {
yield* this.push(_.isMatch(this.value, source));
}
}
function* isMatchWith(source, customizer) {
while (yield* this.pull()) {
yield* this.push(_.isMatch(this.value, source, customizer));
}
}
function* isNaN() {
while (yield* this.pull()) {
yield* this.push(_.isNaN(this.value));
}
}
// isNative doesn't make sense
function* isNil() {
while (yield* this.pull()) {
yield* this.push(_.isNil(this.value));
}
}
function* isNull() {
while (yield* this.pull()) {
yield* this.push(_.isNull(this.value));
}
}
function* isNumber() {
while (yield* this.pull()) {
yield* this.push(_.isNumber(this.value));
}
}
function* isObject() {
while (yield* this.pull()) {
yield* this.push(_.isObject(this.value));
}
}
function* isObjectLike() {
while (yield* this.pull()) {
yield* this.push(_.isObjectLike(this.value));
}
}
function* isPlainObject() {
while (yield* this.pull()) {
yield* this.push(_.isPlainObject(this.value));
}
}
function* isRegExp() {
while (yield* this.pull()) {
yield* this.push(_.isRegExp(this.value));
}
}
function* isSafeInteger() {
while (yield* this.pull()) {
yield* this.push(_.isSafeInteger(this.value));
}
}
function* isSet() {
while (yield* this.pull()) {
yield* this.push(_.isSet(this.value));
}
}
function* isString() {
while (yield* this.pull()) {
yield* this.push(_.isString(this.value));
}
}
function* isSymbol() {
while (yield* this.pull()) {
yield* this.push(_.isSymbol(this.value));
}
}
function* isTypedArray() {
while (yield* this.pull()) {
yield* this.push(_.isTypedArray(this.value));
}
}
function* isUndefined() {
while (yield* this.pull()) {
yield* this.push(_.isUndefined(this.value));
}
}
function* isWeakMap() {
while (yield* this.pull()) {
yield* this.push(_.isWeakMap(this.value));
}
}
function* isWeakSet() {
while (yield* this.pull()) {
yield* this.push(_.isWeakSet(this.value));
}
}
function* lt(other) {
while (yield* this.pull()) {
yield* this.push(_.lte(this.value, other));
}
}
function* lte(other) {
while (yield* this.pull()) {
yield* this.push(_.lte(this.value, other));
}
}
function* toArray() {
while (yield* this.pull()) {
yield* this.push(_.toArray(this.value));
}
}
function* toFinite() {
while (yield* this.pull()) {
yield* this.push(_.toFinite(this.value));
}
}
function* toInteger() {
while (yield* this.pull()) {
yield* this.push(_.toInteger(this.value));
}
}
function* toLength() {
while (yield* this.pull()) {
yield* this.push(_.toLength(this.value));
}
}
function* toNumber() {
while (yield* this.pull()) {
yield* this.push(_.toNumber(this.value));
}
}
function* toPlainObject() {
while (yield* this.pull()) {
yield* this.push(_.toPlainObject(this.value));
}
}
function* toSafeInteger() {
while (yield* this.pull()) {
yield* this.push(_.toSafeInteger(this.value));
}
}
function* toString() {
while (yield* this.pull()) {
yield* this.push(_.toString(this.value));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Math ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Adds something to each element of the input stream.
*
* @static
* @this rq.Context
* @param {*} other The addend.
* @example
* 1 2 3 → add 4 → 5 6 7
* "a" "b" "c" → add "d" → "ad" "bd" "cd"
*/
function* add(other) {
while (yield* this.pull()) {
yield* this.push(_.add(this.value, other));
}
}
/**
* Computes the ceiling of each element of the input stream rounded up
* to `precision`.
*
* @static
* @this rq.Context
* @param {number} [precision=0] The precision to round up to.
* @example
* 4.006 → ceil → 5
* 6.004 → ceil 2 → 6.01
* 6040 → ceil -2 → 6100
*/
function* ceil(precision) {
while (yield* this.pull()) {
yield* this.push(_.ceil(this.value, precision));
}
}
/**
* Divides each element of the input stream by something.
*
* @static
* @this rq.Context
* @param {*} other The divisor.
* @example
* 1 2 3 → divide 2 → 0.5 1 1.5
*/
function* divide(other) {
while (yield* this.pull()) {
yield* this.push(_.divide(this.value, other));
}
}
/**
* Computes the floor of each element of the input stream rounded down
* to `precision`.
*
* @static
* @this rq.Context
* @param {number} [precision=0] The precision to round down to.
* @example
* 4.006 → floor → 4
* 0.046 → floor 2 → 0.04
* 4060 → floor -2 → 4000
*/
function* floor(precision) {
while (yield* this.pull()) {
yield* this.push(_.floor(this.value, precision));
}
}
/**
* Computes the maximum value of the input stream. If the input stream is empty or falsey,
* `undefined` is returned.
*
* @static
* @this rq.Context
* @example
* 4 2 8 6 → max → 8
* (empty) → max → null
*/
function* max() {
yield* this.push(_.max((yield* this.collect())));
}
/**
* This method is like `max` except that it accepts `iteratee` which is
* invoked for each element in the input stream to generate the criterion by which
* the value is ranked. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* {"n": 1} {"n": 2} → maxBy (o)=>{o.n} → {"n": 2}
* // The `property` iteratee shorthand.
* {"n": 1} {"n": 2} → maxBy "n" → {"n": 2}
*/
function* maxBy(iteratee) {
yield* this.push(_.maxBy((yield* this.collect()), iteratee));
}
/**
* Computes the mean of the values in the input stream.
*
* @static
* @this rq.Context
* @example
* 4 2 8 6 → mean → 5
* (empty) → mean → null
*/
function* mean() {
yield* this.push(_.mean((yield* this.collect())));
}
/**
* This method is like `mean` except that it accepts `iteratee` which is
* invoked for each element in the input stream to generate the value to be averaged.
* The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* {"n": 4} {"n": 2} {"n": 8} {"n": 6} → meanBy (o)=>{o.n} → 5
* // The `property` iteratee shorthand.
* {"n": 4} {"n": 2} {"n": 8} {"n": 6} → meanBy "n" → 5
*/
function* meanBy(iteratee) {
yield* this.push(_.meanBy((yield* this.collect()), iteratee));
}
/**
* Computes the minimum value of the input stream. If the input stream is empty or falsey,
* `undefined` is returned.
*
* @static
* @this rq.Context
* @example
* 4 2 8 6 → min → 2
* (empty) → min → null
*/
function* min() {
yield* this.push(_.min((yield* this.collect())));
}
/**
* This method is like `min` except that it accepts `iteratee` which is
* invoked for each element in the input stream to generate the criterion by which
* the value is ranked. The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* {"n": 1} {"n": 2} → minBy (o)=>{o.n} → {"n": 1}
* // The `property` iteratee shorthand.
* {"n": 1} {"n": 2} → minBy "n" → {"n": 1}
*/
function* minBy(iteratee) {
yield* this.push(_.minBy((yield* this.collect()), iteratee));
}
/**
* Multiplies each element of the input stream by something.
*
* @static
* @this rq.Context
* @param {*} other The factor.
* @example
* 1 2 3 → multiply 2 → 2 4 6
*/
function* multiply(other) {
while (yield* this.pull()) {
yield* this.push(_.multiply(this.value, other));
}
}
/**
* Rounds each element of the input stream to `precision`.
*
* @static
* @this rq.Context
* @param {number} [precision=0] The precision to round to.
* @example
* 4.006 → round → 4
* 4.006 → round 2 → 4.01
* 4060 → round -2 → 4100
*/
function* round(other) {
while (yield* this.pull()) {
yield* this.push(_.round(this.value, other));
}
}
/**
* Subtracts something from each element of the input stream.
*
* @static
* @this rq.Context
* @param {*} other The subtrahend.
* @example
* 1 2 3 → subtract 1 → 0 1 2
*/
function* subtract(other) {
while (yield* this.pull()) {
yield* this.push(_.subtract(this.value, other));
}
}
/**
* Computes the sum of the values in the input stream.
*
* @static
* @this rq.Context
* @example
* 4 2 8 6 → sum → 20
* (empty) → sum → 0
*/
function* sum() {
yield* this.push(_.sum((yield* this.collect())));
}
/**
* This method is like `sum` except that it accepts `iteratee` which is
* invoked for each element in the input stream to generate the value to be summed.
* The iteratee is invoked with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* {"n": 4} {"n": 2} {"n": 8} {"n": 6} → sumBy (o)=>{o.n} → 20
* // The `property` iteratee shorthand.
* {"n": 4} {"n": 2} {"n": 8} {"n": 6} → sumBy "n" → 20
*/
function* sumBy(iteratee) {
yield* this.push(_.sumBy((yield* this.collect()), iteratee));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Number ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
function* clamp(start, end) {
while (yield* this.pull()) {
yield* this.push(_.clamp(this.value, start, end));
}
}
function* inRange(start, end) {
while (yield* this.pull()) {
yield* this.push(_.inRange(this.value, start, end));
}
}
/**
* Produces a random number between the inclusive `lower` and `upper` bounds.
* If only one argument is provided a number between `0` and the given number
* is returned. If `floating` is `true`, or either `lower` or `upper` are
* floats, a floating-point number is returned instead of an integer.
*
* **Note:** JavaScript follows the IEEE-754 standard for resolving
* floating-point values which can produce unexpected results.
*
* @static
* @this rq.Context
* @param {number} [lower=0] The lower bound.
* @param {number} [upper=1] The upper bound.
* @param {boolean} [floating] Specify returning a floating-point number.
* @example
* (empty) → random 0 5 → 2 (not tested)
* (empty) → random 5 → 3 (not tested)
* (empty) → random 5 true → 3.2 (not tested)
* (empty) → random 1.2 1.5 → 1.3 (not tested)
*/
function* random(lower, upper, floating) {
while (true) {
yield* this.push(_.random(lower, upper, floating));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - Number ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Assigns own enumerable string keyed properties of source objects to the
* destination object. Source objects are applied from left to right.
* Subsequent sources overwrite property assignments of previous sources.
*
* **Note:** This method mutates `object` and is loosely based on
* [`Object.assign`](https://mdn.io/Object/assign).
*
* @static
* @this rq.Context
* @param {...Object} [sources] The source objects..
* @example
* {"a": 0, "b": 2} → assign {"a": 1, "c": 3} → {"a": 1, "b": 2, "c": 3}
*/
function* assign(...sources) {
while (yield* this.pull()) {
yield* this.push(_.assign(this.value, ...sources));
}
}
// assignIn, assignInWith, assignWith don't make sense
/**
* Creates an array of values corresponding to `paths` of `object`.
*
* @static
* @this rq.Context
* @param {Object} object The object to iterate over.
* @param {...(string|string[])} [paths] The property paths of elements to pick.
* @example
* { "a": [{ "b": { "c": 3 } }, 4] } → at "a[0].b.c" → 3
* { "a": [{ "b": { "c": 3 } }, 4] } → at "a[0].b.c" "a[1]" → [3, 4]
*/
function* at(...paths) {
while (yield* this.pull()) {
if (paths.length === 1) {
yield* this.spread(_.at(this.value, ...paths));
} else {
yield* this.push(_.at(this.value, ...paths));
}
}
}
/**
* Assigns own and inherited enumerable string keyed properties of
* source objects to the destination object for all destination
* properties that resolve to `undefined`. Source objects are applied
* from left to right. Once a property is set, additional values of
* the same property are ignored.
*
* **Note:** This method mutates `object`.
*
* @static
* @this rq.Context
* @param {...Object} [sources] The source objects..
* @example
* {"a": 0, "b": 2} → defaults {"a": 1, "c": 3} → {"a": 0, "b": 2, "c": 3}
*/
function* defaults(...sources) {
while (yield* this.pull()) {
yield* this.push(_.defaults(this.value, ...sources));
}
}
/**
* This method is like `defaults` except that it recursively assigns
* default properties.
*
* **Note:** This method mutates `object`.
*
* @static
* @this rq.Context
* @param {...Object} [sources] The source objects..
* @example
* { "a": { "b": 2 } } → defaultsDeep { "a": { "b": 1, "c": 3 } } → { "a": { "b": 2, "c": 3 } }
*/
function* defaultsDeep(...sources) {
while (yield* this.pull()) {
yield* this.push(_.defaultsDeep(this.value, ...sources));
}
}
/**
* This method is like `find` except that it returns the key of the
* first element `predicate` returns truthy for instead of the element
* itself.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per
* iteration.
* @example
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findKey (o)=>{o.g < 40} → "a"
* // The `matches` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findKey {"g": 1, "a": true} → "c"
* // The `matchesProperty` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findKey ["a", false] → "b"
* // The `property` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findKey "a" → "a"
*/
function* findKey(predicate) {
while (yield* this.pull()) {
yield* this.push(_.findKey(this.value, predicate));
}
}
/**
* This method is like `findKey` except that it iterates over elements
* of a collection in the opposite order.
*
* @static
* @this rq.Context
* @param {Function} [predicate=_.identity] The function invoked per
* iteration.
* @example
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findLastKey (o)=>{o.g < 40} → "c"
* // The `matches` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findLastKey {"g": 1, "a": true} → "c"
* // The `matchesProperty` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findLastKey ["a", false] → "b"
* // The `property` iteratee shorthand.
* {"a": {"u": "b", "g": 36, "a": true}, "b": {"u": "f", "g": 40, "a": false}, "c": {"u": "p", "g": 1, "a": true}} → findLastKey "a" → "c"
*/
function* findLastKey(predicate) {
while (yield* this.pull()) {
yield* this.push(_.findLastKey(this.value, predicate));
}
}
// forIn, forInRight, forOwn don't make sense
/**
* Gets the value at `path` of `object`. If the resolved value is
* `undefined`, the `defaultValue` is returned in its place.
*
* @static
* @this rq.Context
* @param {Array|string} path The path of the property to get.
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
* @example
* { "a": [{ "b": { "c": 3 } }] } → get "a[0].b.c" → 3
* { "a": [{ "b": { "c": 3 } }] } → get ["a", "0", "b", "c"] → 3
* { "a": [{ "b": { "c": 3 } }] } → get "a.b.c" "default" → "default"
*/
function* get(path, defaultValue) {
while (yield* this.pull()) {
yield* this.push(_.get(this.value, path, defaultValue));
}
}
/**
* Checks if `path` is a direct property of `object`.
*
* @static
* @this rq.Context
* @param {Array|string} path The path to check.
* @example
* { "a": { "b": 2 } } → has "a" → true
* { "a": { "b": 2 } } → has "a.b" → true
* { "x": 3 } → has "a" → false
*/
function* has(path) {
while (yield* this.pull()) {
yield* this.push(_.has(this.value, path));
}
}
// hasIn doesn't make sense
/**
* Creates an object composed of the inverted keys and values of `object`.
* If `object` contains duplicate values, subsequent values overwrite
* property assignments of previous values.
*
* @static
* @this rq.Context
* @example
* { "a": 1, "b": 2, "c": 1 } → invert → { "1": "c", "2": "b" }
*/
function* invert() {
while (yield* this.pull()) {
yield* this.push(_.invert(this.value));
}
}
/**
* This method is like `invert` except that the inverted object is generated
* from the results of running each element of `object` thru `iteratee`. The
* corresponding inverted value of each inverted key is an array of keys
* responsible for generating the inverted value. The iteratee is invoked
* with one argument: (value).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @example
* { "a": 1, "b": 2, "c": 1 } → invertBy (v => "group" + v) → { "group1": ["a", "c"], "group2": ["b"] }
*/
function* invertBy(iteratee) {
while (yield* this.pull()) {
yield* this.push(_.invertBy(this.value, iteratee));
}
}
/**
* Invokes the method at `path` of `object`.
*
* @static
* @this rq.Context
* @param {Array|string} path The path of the method to invoke.
* @param {...*} [args] The arguments to invoke the method with.
* @example
* { "a": [{ "b": { "c": [1, 2, 3, 4] } }] } → invoke "a[0].b.c.slice" 1 3 → [2, 3]
*/
function* invoke(path, ...args) {
while (yield* this.pull()) {
yield* this.push(_.invoke(this.value, path, ...args));
}
}
/**
* Creates an array of the own enumerable property names of `object`.
*
* **Note:** Non-object values are coerced to objects. See the
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
* for more details.
*
* @static
* @this rq.Context
* @example
* {"a": 2, "b": 3} → keys → ["a", "b"]
*/
function* keys() {
while (yield* this.pull()) {
yield* this.push(_.keys(this.value));
}
}
/**
* The opposite of `mapValues`; this method creates an object with the
* same values as `object` and keys generated by running each own enumerable
* string keyed property of `object` thru `iteratee`. The iteratee is invoked
* with three arguments: (value, key, object).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @example
* {"a": 1, "b": 2} → mapKeys (v, k) => {k + v} → {"a1": 1, "b2": 2}
*/
function* mapKeys(iteratee) {
while (yield* this.pull()) {
yield* this.push(_.mapKeys(this.value, iteratee));
}
}
/**
* Creates an object with the same keys as `object` and values generated
* by running each own enumerable string keyed property of `object` thru
* `iteratee`. The iteratee is invoked with three arguments:
* (value, key, object).
*
* @static
* @this rq.Context
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @example
* {"a": 1, "b": 2} → mapValues (v, k) => {k + v} → {"a": "a1", "b": "b2"}
*/
function* mapValues(iteratee) {
while (yield* this.pull()) {
yield* this.push(_.mapValues(this.value, iteratee));
}
}
function* merge(...sources) {
while (yield* this.pull()) {
yield* this.push(_.merge(this.value, ...sources));
}
}
function* omit(...props) {
while (yield* this.pull()) {
yield* this.push(_.omit(this.value, props));
}
}
function* pick(...props) {
while (yield* this.pull()) {
yield* this.push(_.pick(this.value, props));
}
}
function* pickBy(predicate) {
while (yield* this.pull()) {
yield* this.push(_.pickBy(this.value, predicate));
}
}
function* result(path, defaultValue) {
while (yield* this.pull()) {
yield* this.push(_.result(this.value, path, defaultValue));
}
}
function* set(path, value) {
while (yield* this.pull()) {
yield* this.push(_.set(this.value, path, value));
}
}
function* toPairs() {
while (yield* this.pull()) {
yield* this.push(_.toPairs(this.value));
}
}
function* transform(iteratee, accumulator) {
while (yield* this.pull()) {
yield* this.push(_.transform(this.value, iteratee, accumulator));
}
}
function* unset(path) {
while (yield* this.pull()) {
yield* this.push(_.unset(this.value, path));
}
}
function* update(path, updater) {
while (yield* this.pull()) {
yield* this.push(_.update(this.value, path, updater));
}
}
function* updateWith(path, updater, customizer) {
while (yield* this.pull()) {
yield* this.push(_.updateWith(this.value, path, updater, customizer));
}
}
function* values() {
while (yield* this.pull()) {
yield* this.push(_.values(this.value));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// lodash wrappers - String ///
/// ///
/// NOTE: These are not streaming! ///
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Converts each input `string` to [camel
* case](https://en.wikipedia.org/wiki/CamelCase).
*
* @static
* @this rq.Context
* @example
* "Foo Bar" → camelCase → "fooBar"
* "--foo-bar--" → camelCase → "fooBar"
* "__FOO_BAR__" → camelCase → "fooBar"
*/
function* camelCase() {
while (yield* this.pull()) {
yield* this.push(_.camelCase(this.value));
}
}
/**
* Converts each input `string`s first letter to upper case and the
* remaining to lower case.
*
* @static
* @this rq.Context
* @example
* "FRED" → capitalize → "Fred"
*/
function* capitalize() {
while (yield* this.pull()) {
yield* this.push(_.capitalize(this.value));
}
}
/**
* Deburrs each input `string` by converting [Latin-1
* Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
* and [Latin
* Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) letters
* to basic Latin letters and removing [combining diacritical
* marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
*
* @static
* @this rq.Context
* @example
* "déjà vu" → deburr → "deja vu"
*/
function* deburr() {
while (yield* this.pull()) {
yield* this.push(_.deburr(this.value));
}
}
/**
* Checks if each input `string` ends with the given target string.
*
* @static
* @this rq.Context
* @param {string} [target] The string to search for.
* @param {number} [position=string.length] The position to search up
* to.
* @example
* "abc" → endsWith "c" → true
* "abc" → endsWith "b" → false
* "abc" → endsWith "b" 2 → true
*/
function* endsWith(target, position) {
while (yield* this.pull()) {
yield* this.push(_.endsWith(this.value, target, position));
}
}
/**
* Converts the characters "&", "<", ">", '"', and "'" in each input
* `string` to their corresponding HTML entities.
*
* **Note:** No other characters are escaped. To escape additional
* characters use a third-party library like
* [_he_](https://mths.be/he).
*
* Though the ">" character is escaped for symmetry, characters like
* ">" and "/" don't need escaping in HTML and have no special meaning
* unless they're part of a tag or unquoted attribute value. See
* [Mathias Bynens's
* article](https://mathiasbynens.be/notes/ambiguous-ampersands)
* (under "semi-related fun fact") for more details.
*
* When working with HTML you should always [quote attribute
* values](http://wonko.com/post/html-escaping) to reduce XSS vectors.
*
* @static
* @this rq.Context
* @example
* "fred, barney, & pebbles" → escape → "fred, barney, &amp; pebbles"
*/
function* escape() {
while (yield* this.pull()) {
yield* this.push(_.escape(this.value));
}
}
/**
* Escapes the `RegExp` special characters "^", "$", "\", ".", "*",
* "+", "?", "(", ")", "[", "]", "{", "}", and "|" in each input
* `string`.
*
* @static
* @this rq.Context
* @example
* "[lodash](https://lodash.com/)" → escapeRegExp → "\\[lodash\\]\\(https://lodash\\.com/\\)"
*/
function* escapeRegExp() {
while (yield* this.pull()) {
yield* this.push(_.escapeRegExp(this.value));
}
}
/**
* Converts each input `string` to
* [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
*
* @static
* @this rq.Context
* @example
* "Foo Bar" → kebabCase → "foo-bar"
* "fooBar" → kebabCase → "foo-bar"
* "__FOO_BAR__" → kebabCase → "foo-bar"
*/
function* kebabCase() {
while (yield* this.pull()) {
yield* this.push(_.kebabCase(this.value));
}
}
/**
* Converts each input `string`, as space separated words, to lower
* case.
*
* @static
* @this rq.Context
* @example
* "--Foo-Bar--" → lowerCase → "foo bar"
* "fooBar" → lowerCase → "foo bar"
* "__FOO_BAR__" → lowerCase → "foo bar"
*/
function* lowerCase() {
while (yield* this.pull()) {
yield* this.push(_.lowerCase(this.value));
}
}
/**
* Converts each input `string`'s first character to lower case.
*
* @static
* @this rq.Context
* @example
* "Fred" → lowerFirst → "fred"
* "FRED" → lowerFirst → "fRED"
*/
function* lowerFirst() {
while (yield* this.pull()) {
yield* this.push(_.lowerFirst(this.value));
}
}
/**
* Pads each input `string` on the left and right sides if it's
* shorter than `length`. Padding characters are truncated if they
* can't be evenly divided by `length`.
*
* @static
* @this rq.Context
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @example
* "abc" → pad 8 → " abc "
* "abc" → pad 8 "_-" → "_-abc_-_"
* "abc" → pad 3 → "abc"
*/
function* pad(length, chars) {
while (yield* this.pull()) {
yield* this.push(_.pad(this.value, length, chars));
}
}
/**
* Pads each input `string` on the right side if it's shorter than
* `length`. Padding characters are truncated if they can't be evenly
* divided by `length`.
*
* @static
* @this rq.Context
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @example
* "abc" → padEnd 6 → "abc "
* "abc" → padEnd 6 "_-" → "abc_-_"
* "abc" → padEnd 3 → "abc"
*/
function* padEnd(length, chars) {
while (yield* this.pull()) {
yield* this.push(_.padEnd(this.value, length, chars));
}
}
/**
* Pads each input `string` on the left side if it's shorter than
* `length`. Padding characters are truncated if they can't be evenly
* divided by `length`.
*
* @static
* @this rq.Context
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @example
* "abc" → padStart 6 → " abc"
* "abc" → padStart 6 "_-" → "_-_abc"
* "abc" → padStart 3 → "abc"
*/
function* padStart(length, chars) {
while (yield* this.pull()) {
yield* this.push(_.padStart(this.value, length, chars));
}
}
/**
* Converts each input `string` to an integer of the specified
* radix. If `radix` is `undefined` or `0`, a `radix` of `10` is used
* unless `value` is a hexadecimal, in which case a `radix` of `16` is
* used.
*
* **Note:** This method aligns with the [ES5
* implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
*
* @static
* @this rq.Context
* @param {number} [radix=10] The radix to interpret `value` by.
* @example
* "08" → parseInt → 8 (not tested)
* "6" "08" "10" → parseInt → 6 8 10 (not tested)
* "a" "b" "c" → parseInt 16 → 10 11 12 (not tested)
*/
function* parseInt(radix) {
while (yield* this.pull()) {
yield* this.push(_.parseInt(this.value, radix));
}
}
/**
* Repeats each input string `n` times.
*
* @static
* @this rq.Context
* @param {number} [n=1] The number of times to repeat the string.
* @example
* "*" → repeat 3 → "***"
* "abc" → repeat 2 → "abcabc"
* "abc" → repeat 0 → ""
*/
function* repeat(n) {
while (yield* this.pull()) {
yield* this.push(_.repeat(this.value, n));
}
}
/**
* Replaces matches for `pattern` in each input `string` with
* `replacement`.
*
* **Note:** This method is based on
* [`String#replace`](https://mdn.io/String/replace). Repeats each
* input string `n` times.
*
* @static
* @this rq.Context
* @param {RegExp|string} pattern The pattern to replace.
* @param {Function|string} replacement The match replacement.
* @example
* "Hi Fred" → replace "Fred" "Barney" → "Hi Barney"
*/
function* replace(pattern, replacement) {
while (yield* this.pull()) {
yield* this.push(_.replace(this.value, pattern, replacement));
}
}
/**
* Converts each input `string` to
* [snake case](https://en.wikipedia.org/wiki/Snake_case).
*
* @static
* @this rq.Context
* @example
* "Foo Bar" → snakeCase → "foo_bar"
* "fooBar" → snakeCase → "foo_bar"
* "--FOO-BAR--" → snakeCase → "foo_bar"
*/
function* snakeCase() {
while (yield* this.pull()) {
yield* this.push(_.snakeCase(this.value));
}
}
/**
* Splits each input `string` by `separator`.
*
* @static
* @this rq.Context
* @param {RegExp|string} separator The separator pattern to split by.
* @param {number} [limit] The length to truncate results to.
* @example
* "a-b-c" → split "-" → ["a", "b", "c"]
* "a-b-c" → split "-" 2 → ["a", "b"]
*/
function* split(separator, limit) {
while (yield* this.pull()) {
yield* this.push(_.split(this.value, separator, limit));
}
}
/**
* Converts each input `string` to
* [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
*
* @static
* @this rq.Context
* @example
* "--foo-bar--" → startCase → "Foo Bar"
* "fooBar" → startCase → "Foo Bar"
* "__FOO_BAR__" → startCase → "FOO BAR"
*/
function* startCase() {
while (yield* this.pull()) {
yield* this.push(_.startCase(this.value));
}
}
/**
* Checks if each input `string` starts with the given target string.
*
* @static
* @this rq.Context
* @param {string} [target] The string to search for.
* @param {number} [position=0] The position to search from.
* @example
* "abc" → startsWith "a" → true
* "abc" → startsWith "b" → false
* "abc" → startsWith "b" 1 → true
*/
function* startsWith(target, position) {
while (yield* this.pull()) {
yield* this.push(_.startsWith(this.value, target, position));
}
}
/**
* Creates a compiled template function that can interpolate data
* properties in "interpolate" delimiters, HTML-escape interpolated
* data properties in "escape" delimiters, and execute JavaScript in
* "evaluate" delimiters. Data properties may be accessed as free
* variables in the template. If a setting object is given, it takes
* precedence over `_.templateSettings` values.
*
* **Note:** In the development build `_.template` utilizes
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* for easier debugging.
*
* For more information on precompiling templates see
* [lodash's custom builds documentation](https://lodash.com/custom-builds).
*
* For more information on Chrome extension sandboxes see
* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
*
* @static
* @this rq.Context
* @param {string} [string=''] The template string.
* @param {Object} [options={}] The options object.
* @param {RegExp} [options.escape=_.templateSettings.escape]
* The HTML "escape" delimiter.
* @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
* The "evaluate" delimiter.
* @param {Object} [options.imports=_.templateSettings.imports]
* An object to import into the template as free variables.
* @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
* The "interpolate" delimiter.
* @param {string} [options.sourceURL='lodash.templateSources[n]']
* The sourceURL of the compiled template.
* @param {string} [options.variable='obj']
* The data object variable name.
* @example
* // Use the "interpolate" delimiter to create a compiled template.
* {"user": "fred"} → template "hello <%= user %>!" → "hello fred!"
*
* // Use the HTML "escape" delimiter to escape data property values.
* {"value": "<script>"} → template "<b><%- value %></b>" → "<b>&lt;script&gt;</b>"
*
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
* {"users": ["fred", "barney"]} → template "<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>" → "<li>fred</li><li>barney</li>"
*
* // Use the internal `print` function in "evaluate" delimiters.
* {"user": "barney"} → template "<% print('hello ' + user); %>!" → "hello barney!"
*
* // Use backslashes to treat delimiters as plain text.
* {"value": "ignored"} → template "<%= '\\<%- value %\\>' %>" → "<%- value %>"
*
* // Use the `variable` option to ensure a with-statement isn't used
* // in the compiled template.
* {"user": "barney"} → template "hi <%= data.user %>!" {"variable": "data"} → "hi barney!"
*/
function* template(string, options) {
var template = _.template(string, options);
while (yield* this.pull()) {
yield* this.push(template(this.value));
}
}
/**
* Converts each input `string`, as a whole, to lower case just
* like [String#toLowerCase](https://mdn.io/toLowerCase).
*
* @static
* @this rq.Context
* @example
* "--Foo-Bar--" → toLower → "--foo-bar--"
* "fooBar" → toLower → "foobar"
* "__FOO_BAR__" → toLower → "__foo_bar__"
*/
function* toLower() {
while (yield* this.pull()) {
yield* this.push(_.toLower(this.value));
}
}
/**
* Converts each input `string`, as a whole, to upper case just
* like [String#toUpperCase](https://mdn.io/toUpperCase).
*
* @static
* @this rq.Context
* @example
* "--foo-bar--" → toUpper → "--FOO-BAR--"
* "fooBar" → toUpper → "FOOBAR"
* "__foo_bar__" → toUpper → "__FOO_BAR__"
*/
function* toUpper() {
while (yield* this.pull()) {
yield* this.push(_.toUpper(this.value));
}
}
/**
* Removes leading and trailing whitespace or specified characters
* from each input `string`.
*
* @static
* @this rq.Context
* @example
* " abc " → trim → "abc"
* "-_-abc-_-" → trim "_-" → "abc"
*/
function* trim(chars) {
while (yield* this.pull()) {
yield* this.push(_.trim(this.value, chars));
}
}
/**
* Removes trailing whitespace or specified characters from each input
* `string`.
*
* @static
* @this rq.Context
* @param {string} [chars=whitespace] The characters to trim.
* @example
* " abc " → trimEnd → " abc"
* "-_-abc-_-" → trimEnd "_-" → "-_-abc"
*/
function* trimEnd(chars) {
while (yield* this.pull()) {
yield* this.push(_.trimEnd(this.value, chars));
}
}
/**
* Removes leading whitespace or specified characters from each input
* `string`.
*
* @static
* @this rq.Context
* @param {string} [chars=whitespace] The characters to trim.
* @example
* " abc " → trimStart → "abc "
* "-_-abc-_-" → trimStart "_-" → "abc-_-"
*/
function* trimStart(chars) {
while (yield* this.pull()) {
yield* this.push(_.trimStart(this.value, chars));
}
}
/**
* Truncates each input `string` if it's longer than the given maximum
* string length. The last characters of the truncated string are
* replaced with the omission string which defaults to"...".
*
* @static
* @this rq.Context
* @param {Object} [options={}] The options object.
* @param {number} [options.length=30] The maximum string length.
* @param {string} [options.omission='...'] The string to indicate text is omitted.
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
* @example
* "hi-diddly-ho there, neighborino" → truncate → "hi-diddly-ho there, neighbo..."
* "hi-diddly-ho there, neighborino" → truncate {length: 24, separator: " "} → "hi-diddly-ho there,..."
* "hi-diddly-ho there, neighborino" → truncate {omission: " [...]"} → "hi-diddly-ho there, neig [...]"
*/
function* truncate(options) {
while (yield* this.pull()) {
yield* this.push(_.truncate(this.value, options));
}
}
/**
* The inverse of `_.escape`; this method converts the HTML entities
* `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding characters.
*
* **Note:** No other HTML entities are unescaped. To unescape additional
* HTML entities use a third-party library like [_he_](https://mths.be/he).
*
* @static
* @this rq.Context
* @example
* "fred, barney, & pebbles" → unescape → "fred, barney, & pebbles"
*/
function* unescape() {
while (yield* this.pull()) {
yield* this.push(_.unescape(this.value));
}
}
/**
* Converts each input `string`, as space separated words, to upper
* case.
*
* @static
* @this rq.Context
* @example
* "--foo-bar" → upperCase → "FOO BAR"
* "fooBar" → upperCase → "FOO BAR"
* "__FOO_BAR__" → upperCase → "FOO BAR"
*/
function* upperCase() {
while (yield* this.pull()) {
yield* this.push(_.upperCase(this.value));
}
}
/**
* Converts the first character of each input `string` to upper case.
*
* @static
* @this rq.Context
* @example
* "fred" → upperFirst → "Fred"
* "FRED" → upperFirst → "FRED"
*/
function* upperFirst() {
while (yield* this.pull()) {
yield* this.push(_.upperFirst(this.value));
}
}
/**
* Splits each input `string` into an array of its words.
*
* @static
* @this rq.Context
* @param {RegExp|string} [pattern] The pattern to match words.
* @example
* "fred, barney, & pebbles" → words → ["fred", "barney", "pebbles"]
*/
function* words() {
while (yield* this.pull()) {
yield* this.push(_.words(this.value));
}
}