fl
v0.1.1
Published
Functional lazy sequence operators
Downloads
174
Maintainers
Readme
fl.js
Functional lazy operators and sequences.
- Uses standard Iterator protocol
- Accepts ES6 generators as lazy sequences
- Designed to collaborate with modules such as pim.js, which provides persistent immutable data structures
API
General value operators
identity
identity( value )
Returns value
.
increment
increment( value )
Returns value + 1
.
decrement
decrement( value )
Returns value - 1
.
isEven
isEven( value )
Returns value % 2 === 0
.
isOdd
isOdd( value )
Returns value % 2 === 1 || value % 2 === -1
.
sum
sum( ...addends )
Returns the sum of 0
and zero or more addends
.
multiply
multiply( ...factors )
Returns the product of 1
and zero or more factors
.
toArray
Sequence().toArray()
// >>> array
toArray( sequence )
// >>> array
Iterates through a sequence and returns its elements in an array.
complement
complement( predicate )
Returns a function that returns the logical negation of the result of applying predicate
.
complement( isEven )(3);
true
compose
compose( ...fns )
Returns the composition of a series of functions fns
, such that compose(f,g,h)(x)
is equivalent to f(g(h(x)))
.
partial
partial( fn, ...args )
Given a function fn
and successive arguments args
fewer in number than the expected number of parameters for fn
, returns a function that will return the result of applying fn
to the concatentation of args
and its own arguments.
addFive = partial( sum, 5 );
addFive(2);
7
rest = partial( dropWhile, function ( value, index ) {
return index < 1;
});
// >>> function
toArray( rest( range(4) ) );
[ 1, 2, 3 ]
toArray( rest( function* () {
yield 2; yield 4; yield 6; yield 8;
}));
[ 4, 6, 8 ]
apply
apply( fn, sequence )
Returns the result of applying fn
with each element in sequence
as arguments.
compare
The default comparator function used with sort
. Determines the ordinal relation between arguments x
and y
.
compare( x, y )
// >>> number
Returns 0
if x
and y
are of equal precedence, returns -1
if x
precedes y
, or returns 1
if y
precedes x
. If x
and y
are logical sequences, then the comparison is evaluated recursively over the respective elements of both sequences.
comparator
Creates a boolean valued comparison operator.
comparator( predicate )
// >>> function
Returns a predicate that returns true
if applying predicate
to each adjacent pairing of its arguments also returns true
, and returns false
otherwise.
nonconsecutive = comparator( compare );
apply( nonconsecutive, 'fireman' ); // >>> true
apply( nonconsecutive, 'balance' ); // >>> true
apply( nonconsecutive, 'ladders' ); // >>> false
increasing
increasing( ...values )
// >>> boolean
Returns true
if arguments are provided in a strictly increasing order (<
) as determined by compare
; otherwise returns false
.
Logically equivalent to comparator( (x,y) => compare(x,y) < 0 )
.
apply( increasing, [0,1,4,9] ); // >>> true
apply( increasing, [1,1,2,3] ); // >>> false
apply( increasing, 'gist' ); // >>> true
apply( increasing, 'bees' ); // >>> false
apply( increasing, Sequence.range().take(5) );
// >>> true
decreasing
decreasing( ...values )
// >>> boolean
Returns true
if arguments are provided in a strictly decreasing order (>
) as determined by compare
; otherwise returns false
.
apply( decreasing, [9,4,1,0] ); // >>> true
apply( decreasing, [3,2,1,1] ); // >>> false
apply( decreasing, 'wronged' ); // >>> true
apply( decreasing, 'sniffed' ); // >>> false
nonincreasing
nonincreasing( ...values )
// >>> boolean
Returns true
if arguments are provided in a monotonically decreasing order (>=
) as determined by compare
; otherwise returns false
.
apply( nonincreasing, 'sniffed' ); // >>> true
nondecreasing
nondecreasing( ...values )
// >>> boolean
Returns true
if arguments are provided in a monotonically increasing order (<=
) as determined by compare
; otherwise returns false
.
apply( nondecreasing, 'bees' ); // >>> true
Sequential functions
first
Sequence().first()
// >>> *
first( sequence )
// >>> *
Returns the first element in sequence
.
first( range(4) );
0
first([]);
undefined
Logically equivalent to take( 1, sequence )().next().value
.
rest
Sequence().rest()
// >>> Sequence
rest( sequence )
// >>> function
Returns a logical sequence of the elements that follow the first
element of sequence
.
toArray( rest([ 0, 1, 2, 3 ]) );
[ 1, 2, 3 ]
toArray( rest([ 1 ]) );
[]
toArray( rest( [] ) );
[]
Sequence.range( 3, Infinity ).rest().take(4).toArray();
[ 4, 5, 6, 7 ]
Logically equivalent to drop( 1, sequence )
.
range
Defines a sequence of numbers from start
up to but excluding end
in increments of step
.
Sequence.range()
Sequence.range( end )
Sequence.range( start, end )
Sequence.range( start, end, step )
// >>> Sequence
range()
range( end )
range( start, end )
range( start, end, step )
// >>> function
Defaults for arguments not provided are: start = 0
, end = Infinity
, step = 1
.
Returns a Sequence
or sequence generator function.
toArray( range(4) );
[ 0, 1, 2, 3 ]
toArray( take( 5, range() ) );
[ 0, 1, 2, 3, 4 ]
toArray( range(-5) );
[]
toArray( range(3,9,2) );
[ 3, 5, 7 ]
iterate
Given a nominally pure function f
and seed value x
, defines an infinite sequence of x
, f(x)
, f(f(x))
, etc.
Sequence.iterate( fn, seed )
// >>> Sequence
iterate( fn, seed )
// >>> function
Returns a Sequence
or sequence generator function.
toArray( take( 5, iterate( increment, 42 ) ) );
[ 42, 43, 44, 45, 46 ]
repeat
Given a value x
, defines a repeating infinite sequence of x
, or a finite sequence of x
repeated up to limit
times.
Sequence.repeat( value )
Sequence.repeat( value, limit )
// >>> Sequence
repeat( value )
repeat( value, limit )
// >>> function
Returns a Sequence
or sequence generator function.
toArray( take( 5, repeat(42) ) );
[ 42, 42, 42, 42, 42 ]
Sequence.repeat( 'foo', 5 );
[ 'foo', 'foo', 'foo', 'foo', 'foo' ]
cycle
Defines an infinite sequence that repeats the items in sequence
indefinitely.
Sequence.cycle()
// >>> Sequence
cycle( sequence )
// >>> function
Returns a Sequence
or sequence generator function.
toArray( take( 10, cycle([3,4,5,6]) ) );
[ 3, 4, 5, 6, 3, 4, 5, 6, 3, 4 ]
Sequence([3,4,5,6]).take(10).toArray();
[ 3, 4, 5, 6, 3, 4, 5, 6, 3, 4 ]
filter
Applies a nominally pure predicate
to each item in sequence
and keeps those items for which predicate
returns logical true.
Sequence().filter( predicate )
// >>> Sequence
filter( predicate, sequence )
// >>> function
Returns a Sequence
, or sequence generator function, consisting of each element x
in this
or sequence
for which the expression !!predicate(x)
would equal true
.
Sequence(["all", "your", "base", "are", "belong"]).filter( function (word) {
return word.length < 4;
});
[ 'all', 'are' ]
remove
Performs a filter
on the complement
of the provided predicate
.
map
Applies fn
to successive items of one or more sequences.
Sequence().map( fn, ...sequences )
// >>> Sequence
map( fn, sequence, ...sequences )
// >>> function
The arity of fn
should correspond with the number of sequences to be mapped.
Returns a Sequence
, or sequence generator function, consisting of the result of applying fn
to successive items taken from sequence
and any additional sequences
, in parallel, until any of sequence
or sequences
is exhausted.
toArray( map( increment, [1,2,3] ) );
[ 2, 3, 4 ]
Sequence([1,2,3]).map( increment ).toArray();
[ 2, 3, 4 ]
toArray( map( sum, [1,2,3], [10,20,30] ) );
[ 11, 22, 33 ]
Sequence([1,2,3]).map( sum, [10,20,30], [100,200,300] ).toArray();
[ 111, 222, 333 ]
Sequence([1,2,3]).map( sum, [10,20] ).toArray();
[ 11, 22 ]
Sequence( iterate increment, 1 ).map( sum, range(10,50,10) ).toArray();
[ 11, 22, 33, 44 ]
reduce
Iteratively calls fn
, with two arguments:
seed
on the first iteration; thereafter, the result of the previous iterationeach successive value in
sequence
.
If no seed
is provided, the first value of the sequence is used as the seed
and reduction proceeds on the remainder of the sequence.
Sequence().reduce( fn, seed )
Sequence().reduce( fn )
// >>> *
reduce( fn, seed, sequence )
reduce( fn, sequence )
// >>> *
Returns the result of the final iteration of fn
. If the length of sequence
is zero, returns the result of calling fn
with no arguments. If the length of sequence
is 1
, the single element of sequence
is returned.
function factorial (n) {
return Sequence.range(n).map( increment ).reduce( multiply );
}
reductions
Produces a sequence of the intermediate values in a reduce
operation.
Sequence().reductions( fn, seed )
Sequence().reductions( fn )
// >>> Sequence
reductions( fn, seed, sequence )
reductions( fn, sequence )
// >>> function
Returns a Sequence
, or sequence generator function, of reductions.
Sequence.range(1,10).reductions( multiply ).toArray();
[ 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 ]
function factorialSequence (n) {
return Sequence.range(n).map( increment ).reductions( multiply );
}
factorialSequence(10).toArray();
[ 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ]
take
Defines a sequence of up to amount
items taken successively from sequence
, or
Sequence().take( amount )
// >>> Sequence
take( amount, sequence )
// >>> function
Returns a Sequence
or sequence generator function.
takeWhile
Defines a sequence of items taken successively from sequence
so long as the expression !!predicate( item )
remains equal to true
.
Sequence().takeWhile( predicate )
// >>> Sequence
takeWhile( predicate, sequence )
// >>> function
Returns a Sequence
or sequence generator function.
Sequence
.range()
.takeWhile( function (x) {
return Math.log(x) < 1;
})
.toArray();
[ 0, 1, 2 ]
drop
Sequence().drop( amount )
// >>> Sequence
drop( amount, sequence )
// >>> function
Returns a sequence of the items in sequence
that would be excluded from the subsequence returned by an equivalent take
operation.
dropWhile
Sequence().dropWhile( predicate )
// >>> Sequence
dropWhile( predicate, sequence )
// >>> function
Returns a sequence of the items in sequence
that would be excluded from the subsequences returned by an equivalent takeWhile
operation.
concat
Concatenates sequences.
Sequence().concat( ...sequences )
// >>> Sequence
concat( sequence, ...sequences )
// >>> function
Returns a single Sequence
, or a sequence generator function, that is the concatentation of each sequence in the order they are provided.
Sequence.range(3).concat( range(5) ).toArray();
[ 0, 1, 2, 0, 1, 2, 3, 4 ]
Sequence('abc').concat('def', 'ghi').toArray();
[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ]
toArray( concat() );
[]
splitAt
Divides a sequence
into two sequences, where the first contains the first n
elements of sequence
, and the second contains the remaining elements of sequence
.
Sequence().splitAt( n )
// >>> array
splitAt( n, sequence )
// >>> array
Returns a two-element array containing both partitions of sequence
.
Sequence('qwerty')
.splitAt(4)
.map( Sequence )
.map( function (s) {
return s.toArray().join('');
});
[ 'quer', 'ty' ]
splitWith
Divides a sequence
into two sequences, where the first contains elements, starting from the head of sequence
, that return logical true when predicate
is applied to the element.
Sequence().splitWith( predicate )
// >>> array
splitWith( predicate, sequence )
// >>> array
Returns a two-element array containing both partitions of sequence
.
function isConsonant (char) {
return /[^aeiouy]/i.test(char);
}
Sequence('schtick')
.splitWith( isConsonant )
.map( Sequence )
.map( function (s) {
return s.toArray().join('');
});
[ 'scht', 'ick' ]
partition
Partitions sequence
into subsequences of size
elements at offsets stride
elements apart, where stride
defaults to size
such that partitions do not overlap. If the final partition is shorter than size
, then: if a padding
sequence is provided, that partition is filled with elements from padding
until it grows to size
; if no padding
exists, the short partition is dropped.
Sequence().partition( size, stride, padding )
Sequence().partition( size, stride )
Sequence().partition( size )
// >>> Sequence
partition( size, stride, padding, sequence )
partition( size, stride, sequence )
partition( size, sequence )
// >>> function
Returns a Sequence
of partitions, or a sequence generator function that returns an iterator over the partitions, where each partition is itself a sequence generator function that returns an iterator over the elements of the partition.
Sequence.range(12).partition(4).map( toArray ).toArray();
[ [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ], [ 8, 9, 10, 11 ] ]
Sequence.range(11).partition(4).map( toArray ).toArray();
[ [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ] ]
Sequence.range(16).partition(4,6).map( toArray ).toArray();
[ [ 0, 1, 2, 3 ], [ 6, 7, 8, 9 ], [ 12, 13, 14, 15 ] ]
Sequence.range(14).partition(4, 6, ['a']).map( toArray ).toArray();
[ [ 0, 1, 2, 3 ], [ 6, 7, 8, 9 ], [ 12, 13, 'a' ] ]
Sequence.range(14).partition(4, 6, 'abc').map( toArray ).toArray();
[ [ 0, 1, 2, 3 ], [ 6, 7, 8, 9 ], [ 12, 13, 'a', 'b' ] ]
Sequence.range(4).partition(10).map( toArray ).toArray();
[]
Sequence.range(4).partition(10,10,[]).map( toArray ).toArray();
[ [ 0, 1, 2, 3 ] ]
partitionBy
Applies fn
to each value in sequence
, partitioning it into subsequences each time fn
returns a new value.
Sequence().partitionBy( fn )
// >>> Sequence
partitionBy( fn, sequence )
// >>> function
Returns a Sequence
of partitions, or a sequence generator function that returns an iterator over the partitions, where each partition is itself a sequence generator function that returns an iterator over the elements of the partition.
Sequence
.range(1,6)
.partitionBy( function (x) { return x === 3 } )
.map( toArray )
.toArray();
[ [ 1, 2 ], [ 3 ], [ 4, 5 ] ]
Sequence( [1,1,1,2,2,3,3] ).partitionBy( isOdd ).map( toArray ).toArray();
[ [ 1, 1, 1 ], [ 2, 2 ], [ 3, 3 ] ]
Sequence( [1,1,1,2,2,3,3] ).partitionBy( isEven ).map( toArray ).toArray();
[ [ 1, 1, 1 ], [ 2, 2 ], [ 3, 3 ] ]
Sequence("Leeeeeerrrrooyyy")
.partitionBy( identity )
.map( toArray )
.toArray();
[ [ 'L' ],
[ 'e', 'e', 'e', 'e', 'e', 'e' ],
[ 'r', 'r', 'r', 'r' ],
[ 'o', 'o' ],
[ 'y', 'y', 'y' ] ]
interleave
Sequence.interleave( ...sequences )
Sequence().interleave( ...sequences )
// >>> Sequence
interleave( ...sequences )
// >>> function
Given one or more sequences
, defines a sequence consisting of the first item from each of the sequences
, continuing with the second item from each of the sequences
, etc., stopping after any one of the sequences
has been exhausted.
Sequence.interleave( range(), [7,8,9] ).toArray();
[ 0, 7, 1, 8, 2, 9 ] // no `3`
interpose
Places a value
between each element in a sequence
.
Sequence().interpose( value )
// >>> Sequence
interpose( value, sequence )
// >>> function
Returns a new logical sequence containing the value
interposed within the elements of the original sequence.
Sequence("dmtr").interpose('e').toArray();
[ 'd', 'e', 'm', 'e', 't', 'e', 'r' ]
sort
Sorts the contents of a finite, homogeneous logical sequence, as directed by a pure function comparator
if provided, or by compare
otherwise. Elements of the sequence which are themselves sequences are compared by recursively comparing the respective elements of both nested sequences.
Sequence().sort( comparator )
Sequence().sort()
// >>> Sequence
sort( comparator, sequence )
sort( sequence )
// >>> function
Returns a new logical sequence containing the sorted elements of the original sequence.
Sequence([ 'abduct', 'abacus', 'abated', 'abate' ])
.map( Sequence )
.sort( compare )
.map( toArray )
.map( function (a) { return a.join(''); } )
.toArray();
[ 'abacus', 'abate', 'abated', 'abduct' ]