repeat-args
v0.1.3
Published
Yet another take at repeating sequences (string, array, array-like, buffer), also in browsers (UMD).
Downloads
9
Maintainers
Readme
repeat-args
Yet another take at repeating sequences (string, array, array-like, buffer), also in browsers (UMD).
API
It's all about repeaters.
- They're functions that can remember and take parameters.
- The essential parameters are a source sequence and a target quantity length.
- Repeaters can't learn, they can only evolve:
When you give a parameter to a repeater,
it will always produce something new,
based on the new parameter and the ones it remembers.
- When you provide the last missing essential parameter, by default you get a sequence with length items from source, repeated in original order if necessary. You can modify this default behavior by configuring the addFunc parameter – see below.
- When an essential parameter remains unknown, you get a new repeater that remembers your new parameter and all the ones that its producer knew.
This module exports a repeater that knows none of the essential parameters, so you have something to start with:
var r = require('repeat-args'), x = '.o°';
All repeaters have this interface:
r(…stuff)
With less than one argument, use an empty string as the source parameter. (Chosen because it is a sequence of length 0, and also a false-y value.)
equal(r().times(2), '');
equal(r().times(0), '');
equal(r().len(2), '');
equal(r().len(0), '');
With at least one argument, of which the first one is recognized as a sequece: Merge all arguments into a sequence of the same type as the first argument, and use that combined sequence as the source parameter.
equal(r.times(3)(x), '.o°.o°.o°');
equal(r.times(3)([x]), ['.o°', '.o°', '.o°']);
equal(r.times(3)([ [x] ]), [ ['.o°'], ['.o°'], ['.o°'] ]);
equal(r('h', 'i', 5, 7).times(0), '');
equal(r('h', 'i', 5, 7).times(2), 'hi57hi57');
equal(r(['h', 'i', 5, 7]).times(2),
['h', 'i', 5, 7, 'h', 'i', 5, 7]);
equal(r([ ['h', 'i', 5, 7] ]).times(2),
[ ['h', 'i', 5, 7], ['h', 'i', 5, 7] ]);
If none of the above was applicable, behave as r.arar(…stuff)
would.
equal(r(6, 9, 'a', 'b').times(2),
[ 6, 9, 'a', 'b', 6, 9, 'a', 'b' ]);
// same as:
equal(r([], 6, 9, 'a', 'b').times(2),
[ 6, 9, 'a', 'b', 6, 9, 'a', 'b' ]);
// to force a string instead:
equal(r('', 6, 9, 'a', 'b').times(2), '69ab69ab');
r.len(q)
Use q
as the length parameter.
r.times(n), r.n(n)
Use "n
times the length of source" as the length parameter.
The formula will be calculated as soon as the source parameter is known,
which might be immediately.
r.arar(…stuff)
Put all (0 or more) arguments into an array (arar = "ARguments ARray") and use that as the source parameter.
equal(r.times(2).arar(), []);
equal(r.times(2).arar(42), [42, 42]);
equal(r.times(2).arar(3.14, 15), [3.14, 15, 3.14, 15]);
r.seq(string | buffer | array | list)
Use the first argument as the source parameter.
The list means anything that Array.prototype.slice
can make an array from.
x = ifSupported(function () { return Buffer.from('.o°'); });
if (x) {
equal(x.length, 4); // in UTF-8, '°' costs 2 bytes.
equal(r.times(3)(x), Buffer.from('.o°.o°.o°'));
equal(12, Buffer.from('.o°.o°.o°').length);
equal(r.len(9)(x), Buffer.from('.o°.o°.')); // 7 chars in 9 bytes
}
r.str(x)
Shorthand for r.seq(String(x))
.
equal(r.times(3).str(), 'undefinedundefinedundefined');
equal(r.times(3).str(42), '424242');
equal(r.times(3).str(3.14, 15), '3.143.143.14');
r.func(add)
Use add
as the addFunc parameter. The addFunc should be a function.
It will be invoked with two arguments accum
and maxN
.
The accum
(accumulator) is a sequence in which elements are collected.
When it is long enough, that will be the repeater's result.
The maxN
argument is a number that tells addFunc up to how many new
elements it shall produce in this invocation.
The addFunc may safely ignore maxN
in cases where it produces at most
one element.
(It's the repeater's job to make sure to either not request less than one
element, or to discard the excess ones.)
If addFunc has produced exaclty one element and it is of another type than the accumulator, that element may be returned as-is. In all other cases (same type, multiple elements, no elements), the addFunc should return a sequence of the same type as the accumulator.
Returning an empty sequence indicates that no more values can be produced, even in future attempts. The repeater then enters futile mode. The addFunc must not make any assumptions about how often the repeater in futile mode will invoke it to request more elements. (At time of writing, it stops immediately.) A repeater may optionally leave futile mode if any new elements are produced. (Not really relevant since the addFunc won't know about that.)
function fiboArg(accum) {
var n = accum.length;
return (accum[n - 1] + accum[n - 2]);
}
equal(r.func(fiboArg).times(4)(1, 1), [ 1, 1, 2, 3, 5, 8, 13, 21 ]);
equal(r.func(fiboArg).len(8)(1, 1), [ 1, 1, 2, 3, 5, 8, 13, 21 ]);
equal(r.func(fiboArg).len(8)('AB', 'rs'), 'ABrssrrs');
equal(r.func(fiboArg).len(6)(['AB', 'rs']),
[ 'AB', 'rs', 'rsAB', 'rsABrs', 'rsABrsrsAB', 'rsABrsrsABrsABrs' ]);
r.mthd(add)
Like r.func
but the addFunc is invoked with just the maxN
argument,
and its invocation context (this
) will be set to the accumulator.
function fiboMtd() { // no named arguments since we ignore maxN
var accum = this, n = accum.length;
return (accum[n - 1] + accum[n - 2]);
}
equal(r.mthd(fiboMtd).times(4)(1, 1), [ 1, 1, 2, 3, 5, 8, 13, 21 ]);
equal(r.mthd(fiboMtd).len(8)(1, 1), [ 1, 1, 2, 3, 5, 8, 13, 21 ]);
equal(r.mthd(fiboMtd).len(8)('AB', 'rs'), 'ABrssrrs');
equal(r.mthd(fiboMtd).len(6)(['AB', 'rs']),
[ 'AB', 'rs', 'rsAB', 'rsABrs', 'rsABrsrsAB', 'rsABrsrsABrsABrs' ]);
Known issues
- It can't work async. Try the
times
function from theasync
module. or promises. - Needs more/better tests and docs.
License
ISC