Usage
All methods are in Idles\ namespace, immutable, pure and auto-curried.
Binary safe, mb_* functions are used for string methods.
The comparison everywhere by default is a weak equality check (==).
Usage example:
use function Idles\{pipe, map, divide, ary, partial, curryN, filter};
use const Idles\_;
pipe(
map(divide(_, 2)),
map(ary(1, partial(\round(...), [_, 0]))),
map(curryN(1, \intval(...))),
filter(fn ($n) => $n % 2)
)([2,3,4,8]);
Lazy evaluation
Most of the functions take any kind of iterable
as a collection parameter and become
lazy when given an Iterator
or Generator
as an input.
When piped intermediate lazy operations are applied to every element of the iterator one after the other without collection all elements in memory array.
Lazy pipelines operate on a "pull," rather than a "push" basis.
Although when given an array
such method will NOT be lazy and return a modified array
like a build-in PHP array_...
function.
The rule is: you will get back the same kind of iterable that you passed in as an argument.
collect function may be used to turn an iterable of any kind into an array.
icon marks lazy methods.
use function Idles\{pipe, map, filter, collect};
$generator = (function () {
$fp = \fopen('/huge/file/with/numbers', 'r');
while (($s = \fgets($fp)) !== false) {
yield $s;
}
})();
$iterator = pipe(
map(fn ($v) => \intval(\trim($v), 10)),
filter(fn ($v) => $v % 2 == 0),
map(fn ($v) => "[$v]")
// ...
)($generator);
// nothing has happened so far, no data has been requested
// now you can iterate over elements of $iterator with foreach
// or convert it into an array in memory by iterator_to_array or collect
$array = collect($iterator);
Array vs Record
The Idles library makes a distinction between arrays and records.
Array has only numerical sequential indexes. This is what the Array
is in JavaScript and many other languages.
Record may have both numerical and string keys.
AKA hash, map, object, hash table, or associative array in other languages.
This is what the Object
is in JavaScript.
icon marks methods that do not retain string keys and return indexed iterables.
filter(fn ($v) => $v == 'a' || $v == 'C')(['a', 'b', 'c' => 'C']); // ['a', 'C']
Placeholder
Idles\_
is a special placeholder used to specify "gaps" within curried or partially applied functions.
use function Idles\{curryN, partial};
use const Idles\_;
$greet = curryN(3, \str_replace(...))('{name}', _, 'Hello, {name}!');
// or
$greet = partial(\str_replace(...), ['{name}', _, 'Hello, {name}!']);
$greet('Alice'); // Hello, Alice!
Array
concat
concat(?iterable $array, $value): iterable
concatAll(array $values): iterable
Concatinates $array
with additional iterables/values
Returns
Numerically indexed concatenated iterable
Example
concat(['a','b'], ['c', 'd'])' // ['a', 'b', 'c', 'd']
concat(['a','b'], 'C'); // ['a', 'b', 'C']
count
count(callable $predicate, ?iterable $collection): int
Counts the number of items in $collection
matching the $predicate
Example
$even = fn ($x) => $x % 2 == 0;
count($even, [1, 2, 3, 4, 5]); // 2
countBy
countBy(callable $iteratee, ?iterable $collection): array
Returns an array: [$iteratee($value)
=> number of times the $iteratee($value)
was found in $collection
]
Example
$numbers = [1.0, 1.1, 1.2, 2.0, 3.0, 2.2];
countBy(\floor(...))($numbers); // [1 => 3, 2 => 2, 3 => 1]
drop
drop(int $n, ?iterable $collection): iterable
Skips the first $n
elemens and returns the rest of the iterable
Example
drop(1, [1, 2, 3]); // [2, 3]
dropRight
dropRight(int $n, ?iterable $collection): iterable
Skips the last $n
elements
Example
dropRight(2, [1, 2, 3]); // [1]
findIndex
findIndex(callable $predicate, ?iterable $collection): int
findIndexFrom(callable $predicate, int $fromIndex, ?iterable $collection): int
Like find
but returns the index of the first element predicate returns truthy for, -1
if not found
Arguments
- $predicate
- ($value, $index, $collection): bool
Example
findIndex(['b', 'a', 'b', 'c'], fn ($v) => $v == 'b', 1); // 2
findIndexFrom(fn ($v) => $v == 'b', -2, ['a','b','a','b','c']) // 3
findLastIndex
findLastIndex(callable $predicate, ?iterable $collection): int
findLastIndexFrom(callable $predicate, int $fromIndex, ?iterable $collection): int
Like find
but returns the index of the last element predicate returns truthy for, -1
if not found
Arguments
- $predicate
- ($value, $index, $collection): bool
Example
findLastIndexFrom(fn ($v) => $v == 'b', 2, ['a', 'b', 'a', 'b']); // 1
flatten
flatten(?iterable $collection): iterable
Flattens iterable a single level deep.
Example
flatten(['a' => 'A', ['b' => 'B'], 'c' => 'C']); // ['A', 'B', 'C']
flattenDeep
flattenDeep(?iterable $collection): iterable
Recursively flattens iterable.
Example
flattenDeep([1, [2, [3, [4]], 5]]); // [1, 2, 3, 4, 5]
flattenDepth
flattenDepth(int $depth, ?iterable $collection): iterable
Recursively flatten array up to depth times.
Example
flattenDepth(2, [1, [2, [3, [4]], 5]]); // [1, 2, 3, [4], 5]
fromPairs
fromPairs(?iterable $collection): array
Creates a new record from a list key-value pairs. The inverse of toPairs
.
Example
fromPairs([['a', 1], ['b', 2], ['c', 3]]); // ['a' => 1, 'b' => 2, 'c' => 3]
head
head(?iterable $collecton)
Gets the first element of iterable
Example
head([1, 2, 3]); // 1
indexOf
indexOf($value, ?iterable $collection): int
indexOfFrom($value, int $fromIndex, ?iterable $collection): int
Returns the index of the first occurrence of $value
in $collection
, else -1.
Example
indexOf(2, [1, 2, 1, 2]); // 1
intersection
intersection(?iterable $record1, ?iterable $record2): array
Returns unique values that are included in both records
Example
intersection(['a', 'a', 'b'], ['c', 'a', 'a']); // ['a']
intersectionBy
intersectionBy(callable $iteratee, ?iterable $record1, ?iterable $record2): array
Like intersection
but invokes $iteratee
for each element before comparison.
Arguments
- $iteratee
- ($value): mixed
Example
intersectionBy('\floor', [2.1, 1.2], [2.3, 3.4]); // [2.1]
intersectionWith
intersectionWith(callable $comparator, ?iterable $record1, ?iterable $record2): array
Like intersection
but invokes $comparator
to compare elements.
Arguments
- $comparator
- ($a, $b): int
Example
intersectionWith(fn ($a, $b) => $a <=> $b, ['a', 'a', 'b'], ['c', 'a', 'a']); // ['a']
join
join(string $separator, ?iterable $collection): string
Joins iterable elements separated by $separator
Example
join('~', ['a', 'b', 'c']); // 'a~b~c'
last
last(?iterable $collecton)
Gets the last element of iterable
Example
last([1, 2, 3]); // 3
nth
nth(int $offset, ?iterable $collection)
Returns the $offset
element. If $offset
is negative the element at index length + $offset
is returned.
Example
$list = ['foo', 'bar', 'baz', 'quux'];
nth(1, $list); // 'bar'
nth(-1, $list); // 'quux'
nth(99, $list); // null
remove
remove(int $start, int $count, ?iterable $iterable): array
Removes items from $iterable
starting at $start
and containing $count
elements.
Example
remove(2, 3, [1,2,3,4,5,6,7,8]); // [1,2,6,7,8]
slice
slice(int $start, int ?$end, ?iterable $collection): iterable
Retruns a slice of $iterable
from $start
up to, but not including, $end
.
Example
$a = ['a','b','c','d','e'];
slice(1, 3, $a2); // ['b','c']
slice(1, -2, $a2); // ['b','c']
slice(-4, -2, $a2); // ['b','c']
take
take(int $n, ?iterable $collection): iterable
Takes n first elements from iterable
Example
take(2, [1, 2, 3]); // [1, 2]
takeRight
takeRight(int $n, ?iterable $collection): array
Returns a slice of iterable with n elements taken from the end.
Example
takeRight(2, [1, 2, 3]); // [2, 3]
uniq
uniq(?iterable $collection): array
Removes duplicates using ===
Example
uniq([1, 1, 2, '1']); // [1, 2, '1']
uniqueBy
uniqBy(callable $iteratee, ?iterable $collection): array
Like uniq
but apply $iteratee
fist
Arguments
- $iteratee
- ($value): mixed
Example
uniqBy(\abs(...))([-1, -5, 2, 10, 1, 2]); // [-1, -5, 2, 10]
uniqWith
uniqWith(callable $predicate, ?iterable $collection): array
Like uniq
but uses $predicate
to compare elements
Arguments
- $predicate
- ($a, $b): bool
Example
uniqWith(fn ($a, $b) => $a == $b)([1, '1', 2, 1]); // [1, 2]
without
without(array $values, ?iterable $collection): iterable
Returns $iterable
without $values
Example
without([1, 2], [2, 1, 2, 3]); // [3]
zip
zip(iterable $a, iterable $b): iterable
zipAll(array $iterables): iterable
Creates an iterable of grouped elements, the first of which contains the first elements of the given iterables, the second of which contains the second elements, and so on.
Example
$a = ['a', 'b' ];
$aa = ['AA','BB'];
zip($a, $aa); // [ ['a', 'AA'], ['b', 'BB'] ]
zipWith
zipWith(callable $iteratee, iterable $a, iterable $b): iterable
Like zip
except that it accepts $iteratee
to specify how grouped values should be combined.
Example
$a = ['a', 'b' ];
$aa = ['AA','BB'];
zipWith(fn ($a,$b) => $a.'='.$b, $a, $aa); // ["a=AA", "b=BB"]
Collection
all
all(?callable $predicate, ?iterable $collection): bool
Checks if $predicate
returns truthy
for all elements of $collection
. Stop once it returns falsey
Arguments
- $predicate
- ($value): bool
Example
every('\is_numeric')([1,2,3]); // true
$users = [
[ 'user' => 'barney', 'age' => 36, 'active' => true ],
[ 'user' => 'fred', 'age' => 40, 'active' => true ]
];
all(property('active'))($users); // true
any
any(callable $predicate, ?iterable $collection): bool
Checks if $predicate
returns truthy for any element of $collection
. Stops on first found.
Arguments
- $predicate
- ($value, $key, $collection): bool
Example
$users = [
[ 'user' => 'barney', 'active' => false ],
[ 'user' => 'fred', 'active' => true ]
];
any(fn ($r) => $r['active'] == true, $users); // true
each
each(callable $iteratee, ?iterable $collection): iterable
Iterates over elements of $collection
. Iteratee may exit iteration early by returning false
.
Arguments
- $iteratee
- ($value, $key, $collection): ?bool
Example
each(fn ($v) => print_r($v), [1,2,3]);
filter
filter(callable $predicate, ?iterable $collection): iterable
Returns elements $predicate
returns truthy for.
Arguments
- $predicate
- ($value, $key, $collection): bool
Example
filter('is_numeric', ['a', 'b', 13]); // [13]
find
find(?callable $predicate, ?iterable $collection)
findFrom(?callable $predicate, int $fromIndex, ?iterable $collection)
Returns the first element $predicate
returns truthy for.
Arguments
- $predicate
- ($value): bool
flatMap
flatMap(callable $iteratee, ?iterable $collection): iterable
Arguments
- $iteratee
- ($value, $key, $collection): mixed
Example
flatMap(fn ($n) => [$n, $n], [1,2]); // [1, 1, 2, 2]
flatMapDeep
flatMapDeep(callable $iteratee, ?iterable $collection): iterable
Like flatMap
but recursively flattens the results.
Arguments
- $iteratee
- ($value, $key, $collection): mixed
Example
flatMapDeep(fn ($n) => [[[$n, $n]]], [1, 2]); // [1, 1, 2, 2]
flatMapDepth
flatMapDepth(callable $iteratee, int $depth, ?iterable $collection): iterable
Like flatMap
but flattens the mapped results up to $depth
times
Arguments
- $iteratee
- ($value, $key, $collection): mixed
Example
flatMapDepth(fn ($n) => [[[$n, $n]]], 2, [1, 2]); // [[1, 1], [2, 2]]
groupBy
groupBy(callable $iteratee, ?iterable $collection): array
Creates an array composed of keys generated from running each value through $iteratee
.
Arguments
- $iteratee
- ($value): mixed
Example
groupBy('strlen')(['one', 'two', 'three']); // [ '3' => ['one', 'two'], '5' => ['three'] ]
includes
includes($value, ?iterable $collection): bool
includesFrom($value, int $fromIndex, ?iterable $collection): bool
Checks if $value
is in $collection
.
Example
includes(1, ['a' => 1, 'b' => 2]); // true
indexBy
indexBy(callable $iteratee, ?iterable $collection): iterable
Creates a record composed of keys generated from the results of running each element of $collection
through $iteratee
.
Arguments
- $iteratee
- ($value): string|int
Example
$a = [ [ 'code' => 97 ], [ 'code' => 100 ] ];
indexBy(fn ($r) => \chr($r['code']), $a); // ['a' => [ 'code' => 97 ], 'd' => [ 'code' => 100 ]],
map
map(callable $iteratee, ?iterable $collection)
Run each element in $collection
through $iteratee
.
Arguments
- $iteratee
- ($value, $key, $collection): mixed
Example
map(fn ($n) => $n * $n, [4, 8]); // [16, 64]
orderBy
orderBy(array $iteratees, array $orders, ?iterable $collection)
Like sortBy
but allows specifying the sort orders
Arguments
- $iteratees
- [(mixed $value): mixed]
- $orders
- ['asc'|'desc']
Example
$users = [
[ 'user' => 'fred', 'age' => 48 ],
[ 'user' => 'barney', 'age' => 34 ],
[ 'user' => 'fred', 'age' => 40 ],
[ 'user' => 'barney', 'age' => 36 ]
];
orderBy([property('user'), property('age')], ['asc', 'desc'], $users);
/*
[
[ 'user' => 'barney', 'age' => 36 ],
[ 'user' => 'barney', 'age' => 34 ],
[ 'user' => 'fred', 'age' => 48 ],
[ 'user' => 'fred', 'age' => 40 ]
]
*/
partition
partition(callable $predicate, ?iterable $collection): array
Split $collection
into two groups, the first of which contains elements $predicate
returns truthy for, the second of which contains elements $predicate
returns falsey for.
Arguments
- $predicate
- (mixed $value): bool
Example
partition(
fn ($v) => stripos($v, 'A') !== false,
['a' => 'AA', 'b' => 'BB', 'c' => 'AAA']
);
// [['a' => 'AA', 'c' => 'AAA'], ['b' => 'BB']]
reduce
reduce(callable $iteratee, $accumulator, ?iterable $collection)
Reduces $collection
to a value which is the accumulated result of running each element in collection through $iteratee
Arguments
- $iteratee
- ($accumulator, $value, $key, $collection): mixed
Example
reduce(ary(2, subtract(...)), 0, [1, 2, 3, 4]); // -10
resolve
resolve(array $resolvers, array $record): array
Adds new properties to $record
using $resolvers
.
Arguments
- $resolvers
- [string => callable]
Example
$users = [
[ 'name' => 'Steve', 'surname' => 'Jobs' ],
[ 'name' => 'Bill', 'surname' => 'Gates' ]
];
map(
resolve([
'initials' => fn ($r) => $r['name'][0].$r['surname'][0]
]),
$users
);
/*
[
[ 'name' => 'Steve', 'surname' => 'Jobs', 'initials' => 'SJ' ],
[ 'name' => 'Bill', 'surname' => 'Gates', 'initials' => 'BG' ]
]
*/
sort
sort(array $comparator, ?iterable $collection): array
Sorts $collection
using $comparator
comparison ($a <=> $b
) function
Arguments
- $comparator
- (mixed $a, mixed $b): int
Example
$diff = fn ($a, $b) => $a - $b;
sort($diff, [4,2,7,5]); // [2, 4, 5, 7]
sortBy
sortBy(array $comparators, ?iterable $collection): array
Sorts $collection
in ascending order according to $comparators
.
Arguments
- $comparators
- [(mixed $value): mixed]
Example
$users = [
[ 'user' => 'fred', 'age' => 48 ],
[ 'user' => 'barney', 'age' => 36 ],
[ 'user' => 'fred', 'age' => 40 ],
[ 'user' => 'barney', 'age' => 34 ]
];
sortBy([property('user'), property('age')], $users);
/*
[
[ 'user' => 'barney', 'age' => 34 ],
[ 'user' => 'barney', 'age' => 36 ],
[ 'user' => 'fred', 'age' => 40 ],
[ 'user' => 'fred', 'age' => 48 ]
]
*/
sortWith
sortWith(array $comparators, ?iterable $collection): array
Sorts a $collection
according to an array of comparison ($a <=> $b
) functions
Arguments
- $comparators
- [(mixed $a, mixed $b): int]
Example
$people = [
[ 'name' => 'clara', 'age' => 40],
[ 'name' => 'bob', 'age' => 30],
[ 'name' => 'alice', 'age' => 40],
];
sortWith(
[ descend(prop('age')), ascend(prop('name')) ],
$people
);
// alice, clara, bob
values
values(?iterable $collection): iterable
Returns an indexed iterable of values in $collection
.
Example
values(['a' => 'AA', 'b' => 'BB']); // ['AA', 'BB']
Function
always
always($value)
Returns a function that always returns the given value.
applyTo
applyTo($value, callable $interceptor)
Returns $interceptor($value)
.
Example
$n13 = applyTo(13);
$n13(add(100)); // 113
ary
ary(int $n, callable $fn): callable
Creates a function that invokes $fn
, with up to $n
arguments, ignoring any additional arguments.
Example
map(ary(1, '\intval'), ['6', '8', '10']); // [6, 8, 10]
ascend
ascend(callable $func, $a, $b): callable
Makes an ascending comparator function out of a function that returns a value that can be compared with <=>
Example
$byAge = ascend(prop('age'));
$people = [
[ 'name' => 'Emma', 'age' => 70 ],
[ 'name' => 'Peter', 'age' => 78 ],
[ 'name' => 'Mikhail', 'age' => 62 ],
];
sort($byAge, $people); // Mikhail, Emma, Peter
attempt
attempt(callable $fn)
Calls $fn
, returning either the result or the caught exception.
Example
attempt(fn () => 'A'); // A
attempt(fn () => throw new \Exception('Error')); // Exception('Error')
compose
compose(callable ...$funcs): callable
flowRight(array $funcs): callable
Like pipe
but invokes the functions from right to left.
Example
compose('\strtoupper', fn ($s) => 'hello '.$s, '\trim')(' fred '); // 'HELLO FRED'
curry
curry(callable $f): callable
curryN(int $arity, callable $f): callable
\Idles\_
const may be used as a placeholder.
Example
use const \Idles\_;
$abc = fn ($a, $b, $c = 'c') => $a.$b.$c;
curry($abc)('a')('b')('c'); // 'abc'
curryN(2, $abc)('a')('b'); // 'abc'
curry($abc)(_, 'b')(_, 'c')('a'); // 'abc'
curryRight
curryRight(callable $f): callable
curryRightN(int $arity, callable $f): callable
Like curry
but arguments are prepended.
Example
use const \Idles\_;
$abc = fn ($a, $b, $c = 'c') => $a.$b.$c;
curryRight($abc)('c')('b')('a'); // 'abc'
curryRight($abc)('b','c')('a'); // 'abc'
curryRightN(2, $abc)('b')('a'); // 'abc'
descend
descend(callable $func, $a, $b): callable
Makes an descending comparator function out of a function that returns a value that can be compared with <=>
Example
$byAge = descend(prop('age'));
$people = [
[ 'name' => 'Emma', 'age' => 70 ],
[ 'name' => 'Peter', 'age' => 78 ],
[ 'name' => 'Mikhail', 'age' => 62 ],
];
sort($byAge, $people); // Peter, Emma, Mikhail
flip
flip(callable $fn): callable
Returns a new curried function with the first two arguments reversed
Example
flip(fn ($a, $b, $c, $d) => [$a, $b, $c, $d])(1, 2)(3, 4); // [2, 1, 3, 4]
juxt
juxt(array $funcs): callable
Applies a list of functions to a list of values.
Example
juxt([\max(...), \min(...)])(1,2,3,4); // [4,1]
$isOdd = fn ($n) => $n % 2;
juxt([filter($isOdd), remove($isOdd)])([1,2,3,4,5,6,7,8,9]);
// [[1,3,5,7,9], [2,4,6,8]]
memoize
memoize(callable $func): callable
memoizeWith(callable $resolver, callable $func): callable
Creates a function that memoizes the result of $func
. $resolver
returns map cache key, args[0] by default.
Arguments
- $resolver
- (...$args): string|int
negate
negate(callable $predicate): callable
Creates a function that negates the result of the $predicate
function.
Example
$isEven = fn ($n) => $n % 2 == 0;
filter(negate($isEven), [1, 2, 3, 4, 5, 6]); // [1, 3, 5]
once
once(callable $fn): callable
$fn
is only called once, the first value is returned in subsequent invocations.
Example
$addOneOnce = once(fn ($x) => $x + 1);
$addOneOnce(10); // 11
$addOneOnce(50); // 11
partial
partial(callable $fn, array $partials): callable
Creates a function that invokes $fn
with $partials
prepended to the arguments. \Idles\_
const may be used as a placeholder.
Example
use const \Idles\_;
$abcd = fn ($a, $b, $c, $d) => $a.$b.$c.$d;
partial($abcd, ['a', _, 'c'])('b', 'd'); // 'abcd'
partialRight
partialRight(callable $fn, array $partials): callable
Like partial
but $partials
are appended.
Example
use const \Idles\_;
$abcd = fn ($a, $b, $c, $d) => $a.$b.$c.$d;
partialRight($abcd, ['b', _, 'd'])('a', 'c')); // 'abcd'
pipe
pipe(callable ...$funcs): callable
flow(array $funcs): callable
Left-to-right function composition. The first argument may have any arity; the remaining arguments must be unary.
Example
pipe('\trim', '\strtoupper')(' hello '); // 'HELLO'
tap
tap(callable $interceptor, $value)
Calls $interceptor($value)
then returns the original $value
times
times(callable $iteratee, int $n): array
Calls the iteratee $n
times, returning an array of the results of each invocation.
Arguments
- $iteratee
- (int $index): mixed
Example
times(fn($i) => "$i", 3); // ['0', '1', '2']
tryCatch
tryCatch(callable $tryer, callable $catcher, $value)
Calls $tryer
, if it throws, calls $catcher
Arguments
- $tryer
- ($value): mixed
- $catcher
- (\Exception $e, $value): mixed
Example
tryCatch(fn ($v) => "[$v]", fn ($err, $value) => [$err, $value])('A'); // '[A]'
tryCatch(
fn ($v) => throw new \Exception('Error'),
fn (\Exception $err, $value) => [$err->getMessage(), $value]
)('A'); // ['Error', 'A']
unary
unary(callable $fn): callable
Logic
allPass
allPass(array $predicates): callable
Returns a function that checks if its arguments pass all $predicates
.
Arguments
- $predicates
- [(mixed ...$args): bool]
Example
$bothStrings = fn (...$args) => all(ary(1, '\is_string'), $args);
$equal = fn ($a, $b) => $a == $b;
allPass([$bothStrings, $equal])('a', 'b'); // false
allPass([$bothStrings, $equal])('a', 'a'); // true
allPass([$bothStrings, $equal])(1, 1); // false
anyPass
anyPass(array $predicates): callable
Returns a function that checks if its arguments pass any of the $predicates
.
Arguments
- $predicates
- [(mixed ...$args): bool]
Example
$bothStrings = fn (...$args) => all(ary(1, '\is_string'), $args);
$equal = fn ($a, $b) => $a == $b;
anyPass([$bothStrings, $equal])('a', 'b'); // true
anyPass([$bothStrings, $equal])('1', 2); // false
anyPass([$bothStrings, $equal])(1, 1); // true
both
both(callable $func1, callable $func2): callable
Resulting function returns $func1(...$args)
if it is falsy or $func2(...$args)
otherwise, short-circuited
Arguments
- $func1
- (mixed ...$args): mixed
- $func2
- (mixed ...$args): mixed
Example
both(identity(...), always(''))('value'); // ''
both(always('a'), identity(...))('b'); // b
cond
cond(array $pairs): callable
Iterates over $pairs
and invokes the corresponding function of the first predicate to return truthy.
Arguments
- $pairs
- [callable => callable]
Example
$fn = cond([
[fn ($v) => $v == 0, fn () => 'water freezes at 0°C'],
[fn ($v) => $v == 100, fn () => 'water boils at 100°C'],
[fn () => true, fn ($temp) => "nothing special happens at $temp °C"]
]);
$fn(0); // 'water freezes at 0°C'
$fn(50); // 'nothing special happens at 50 °C'
$fn(100); // 'water boils at 100°C'
defaultTo
defaultTo($default)($value)
Returns $value
?? $default
Example
defaultTo(10, null); // 10
either
either(callable $func1, callable $func2): callable
Resulting function returns $func1(...$args)
if it is truthy or $func2(...$args)
otherwise, short-circuited.
Arguments
- $func1
- (mixed ...$args): mixed
- $func2
- (mixed ...$args): mixed
Example
either(always('a'), identity(...))('b'); // a
either(always(''), identity(...))('b'); // b
ifElse
ifElse(callable $predicate, callable $onTrue, callable $onFalse): callable
Resulting function returns $onTrue(...$args)
if $predicate(...$args)
is truthy or $onFalse(...$args)
otherwise.
Arguments
- $predicate
- (mixed ...$args): bool
- $onTrue
- (mixed ...$args): mixed
- $onFalse
- (mixed ...$args): mixed
Example
$f = ifElse(equals('a'), always('T'), always('F'));
$f('a'); // T
$f('b'); // F
not
not($a): bool
unless
unless(callable $predicate, callable $whenFalse, mixed $value)
Returns $predicate($value) ? $value : $whenFalse($value)
Arguments
- $predicate
- (mixed $value): bool
- $whenFalse
- (mixed $value): mixed
Example
$safeInc = unless(\is_null(...), inc(...));
$safeInc(null); // null
$safeInc(1); // 2
when
when(callable $predicate, callable $whenTrue, mixed $value)
Returns $predicate($value) ? $whenTrue($value) : $value
Arguments
- $predicate
- (mixed $value): bool
- $whenTrue
- (mixed $value): mixed
Example
$truncate = when(
pipe(size(...), gt(_, 10)),
pipe(partial(\mb_substr(...), [_, 0, 10]), fn ($s) => $s.'…')
);
$truncate('12345'); // '12345'
$truncate('0123456789ABC'); // '0123456789…'
Math
add
add(int|float $a, int|float $b): int|float
Example
add(100)(13); // 113
dec
dec(int $number): int
divide
divide(int|float $a, int|float $b): int|float
gt
gt($a, $b): bool
Example
gt(100)(13); // true
gte
gte($a, $b): bool
Example
gte(13)(13); // true
inc
inc(int $number): int
lt
lt($a, $b): bool
Example
lt(100)(13); // false
lte
lte($a, $b): bool
Example
lte(13)(13); // true
modulo
modulo(int|float $a, int|float $b): int
multiply
multiply(int|float $a, int|float $b): int|float
round
round(int $precision, int|float $number): float
Rounds $number
to specified $precision
subtract
subtract(int|float $a, int|float $b): int|float
sum
sum(?iterable $collection): int|float
Sums elements in iterable
Example
sum([4, 2, 8, 6]); // 20
sumBy
sumBy(?callable $iteratee, ?iterable $collection): int|float
Like sum
but $iteratee
is invoked for each element in iterable to generate the value to be summed.
Example
$ns = [[ 'n'=> 4 ], [ 'n'=> 2 ], [ 'n'=> 8 ], [ 'n'=> 6 ]];
sumBy(property('n'), $ns); // 20
Record
assignDeep
assignDeep(array $iterables): array
Merges properties recursively, numeric keys are overwritten.
Example
$a = ['a' => ['b' => '1', 'c' => 'C'], ['e' => 'E'], 'x'];
$b = ['a' => ['b' => '2', 'd' => 'D'], ['f' => 'F'], 'y'];
assignDeep([$a, $b]);
// ['a' => ['b' => '2', 'c' => 'C', 'd' => 'D'], ['e' => 'E', 'f' => 'F'], 'y']
defaults
defaults(?iterable $record1, ?iterable $record2): array
defaultsAll(array $iterables)
Merges properties from right to left, numeric keys are overwritten.
Example
defaultsAll([ ['actual', 'a'=>1], ['default', 'b'=>2], ['a'=>3] ]) // ['actual', 'a' => 1, 'b' => 2]
evolve
evolve(array $transformations, ?iterable $record): array
Creates a new record by recursively calling transformation functions with $record
properties.
Arguments
- $transformations
- [string|int => (mixed $value): mixed]
Example
$tomato = ['firstName' => ' Tomato ', 'data' => ['elapsed' => 100, 'remaining' => 1400], 'id' => 123];
$transformations = [
'firstName' => '\trim',
'lastName' => '\trim', // Will not get invoked.
'data' => [
'elapsed' => add(1),
'remaining' => add(-1)
]
];
evolve($transformations)($tomato);
// ['firstName' => 'Tomato', 'data' => ['elapsed' => 101, 'remaining' => 1399], 'id' => 123]
extend
extend(?iterable $source1, ?iterable $source2): array
extendAll(array $iterables): array
Merges properties, numeric keys are overwritten.
Example
extend(
['a', 'c' => 'C'],
['b', 'd' => 'D']
); // ['b', 'c' => 'C', 'd' => 'D']
has
has(string|int $key, ?iterable $record): bool
Checks if $record
has $key
Example
$r = ['a' => 'A];
has('a', $r); // true
hasPath
hasPath(string|int|array $path, ?iterable $record): bool
Checks if $path
exists in $record
Example
$r = [ 'a' => [ 'b' => 2 ] ];
hasPath('a', $r); // true
hasPath('a.b', $r); // true
hasPath(['a', 'b'], $r); // true
invert
invert(?iterable $collection): array
Replaces keys with values. Duplicate keys are overwritten.
Example
invert([ 'a' => 1, 'b' => 2, 'c' => 1 ]); // [1 => 'c', 2 => 'b']
keys
keys(?iterable $record): iterable
Returns an indexed iterable of keys in $record
.
Example
keys([ 'a'=> 1, 'b'=> 2, 'c'=> 3 ]); // ['a', 'b', 'c']
merge
merge(?iterable $source1, ?iterable $source2): array
mergeAll(array $iterables): array
Merges properties, numeric keys are appended.
Example
merge(['a', 'c' => 'C'], ['b', 'd' => 'D']); // ['a', 'b', 'c' => 'C', 'd' => 'D']
mergeDeep
mergeDeep(array $iterables): array
Merges properties recursively, numeric keys are appended.
Example
$a = ['a' => ['b' => 1, 'c' => 'C'], ['e' => 'E'], 'x'];
$b = ['a' => ['b' => 2, 'd' => 'D'], ['f' => 'F'], 'y'];
mergeDeep([$a, $b]);
// ['a' => ['b' => [1, 2], 'c' => 'C', 'd' => 'D'], ['e' => 'E'], 'x', ['f' => 'F'], 'y'],
mergeLeft
mergeLeft(?iterable $left, ?iterable $right): array
calls merge($right, $left)
Example
$resetToDefault = mergeLeft(['x' => 0]);
$resetToDefault(['x' => 5, 'y' => 2]); // ['x' => 0, 'y' => 2]
mergeWith
mergeWith(callable $customizer, ?iterable $left, ?iterable $right): array
Like merge
but if a key exists in both records, $customizer
is called to the values associated with the key
Arguments
- $customizer
- (mixed $a, mixed $b): mixed
Example
mergeWith(concat(...), ['a' => [1], 'b' => [2]], ['a' => [3], 'b' => [4]]); // ['a' => [1,3], 'b' => [2,4]]
modifyPath
modifyPath(array|string|int $path, callable $updater, ?iterable $record)
Creates new record by applying an $updater
function to the value at the given $path
.
Arguments
- $updater
- (mixed $value): mixed
Example
$a = [ 'a' => [ [ 'b' => [ 'c' => 3 ] ] ] ];
modifyPath(['a',0,'b','c'], fn ($n) => $n*$n, $a); // [ 'a' => [ [ 'b' => [ 'c' => 9 ] ] ] ]
objOf
objOf(string $key, $value): array
Creates an array
containing a single key => value pair.
Example
$matchPhrases = compose(
objOf('must'),
map(objOf('match_phrase'))
);
$matchPhrases(['foo', 'bar', 'baz']);
// ["must" => [["match_phrase" => 'foo'], ["match_phrase" => 'bar'], ["match_phrase" => 'baz']]]
omit
omit(array $keys, ?iterable $collection): iterable
The opposite of pick
. Returns record without $keys
.
Example
omit(['a', 'd'], ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]);
// ['b' => 2, 'c' => 3]
omitBy
omitBy(callable $predicate, ?iterable $record): iterable
The opposite of pickBy
. Returns properties of $record
that $predicate
returns falsey for.
Example
omitBy(unary('\is_int'), ['a' => 1, 'b' => '2', 'c' => 3]); // ['b' => '2']
path
path(array|string $path, ?iterable $collection)
pathOr($default, array|string $path, ?iterable $collection)
Retrieve the value at a given path.
Example
$rec = [ 'a' => [[ 'b' => [ 'c' => 3 ] ]] ];
path(['a', '0', 'b', 'c'], $rec); // 3
path('a[0].b.c', $rec); // 3
pathOr('default', 'a.b.c', $rec); // 'default'
paths
paths(array $paths, ?iterable $collection): array
Keys in, values out. Order is preserved.
Example
$a = [ 'a' => [ [ 'b' => [ 'c' => 3 ] ], 4] ];
paths([['a',0,'b','c'], ['a',0,'z'], ['a',1]], $a); // [3, null, 4]
paths(['a.0.b.c', 'a.0.z', 'a.1'], $a); // [3, null, 4]
pick
pick(array $keys, ?iterable $collection): iterable
Returns record containing only $keys
Arguments
- $keys
- [string|int]
Example
pick(['a', 'd'], ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]);
// ['a' => 1, 'd' => 4]
pickBy
pickBy(callable $predicate, ?iterable $record): iterable
Returns record containing only keys $predicate
returns truthy for.
Arguments
- $predicate
- ($value, $key): bool
Example
$isUpperCase = fn ($val, $key) => \strtoupper($key) == $key;
pickBy($isUpperCase, ['a' => 1, 'b' => 2, 'A' => 3, 'B' => 4]);
// ['A' => 3, 'B' => 4]
pluck
pluck(string|int $key, ?iterable $collection)
Returns a new array by plucking the same named property off all records in the array supplied.
Example
pluck(0, [[1, 2], [3, 4]]); // [1, 3]
pluck('val', ['a' => ['val' => 3], 'b' => ['val' => 5]]); // ['a' => 3, 'b' => 5]
prop
prop(string|int $key, ?iterable $record)
propOr($default, string|int $key, ?iterable $record)
Return the specified property.
Example
propOr('NO', 'b', ['a' => 'A']); // 'NO'
propEq
propEq(string|int $key, $value, ?iterable $record): bool
Returns $record[$key] == $value
Example
propEq('a', 'A', ['a' => 'A']); // true
setPath
setPath($path, $value, ?iterable $record)
Return copy $record
with $path
set with $value
Example
$a = [ 'a' => [ [ 'b' => [ 'c' => 3 ] ] ] ];
setPath(['a',0,'b','c'], 113, $a);
// [ 'a' => [ [ 'b' => [ 'c' => 113 ] ] ] ]
toPairs
toPairs(?iterable $record): iterable
Converts a record into an array of [$key, $value]
Example
toPairs(['a' => 1, 'b' => 2, 'c' => 3]); // [['a', 1], ['b', 2], ['c', 3]]
where
where(array $spec, ?iterable $record): bool
Checks if $record
satisfies the spec by invoking the $spec
properties with the corresponding properties of $record
.
Arguments
- $spec
- [string => ($value): bool]
Example
$a = ['a' => 'A', 'b' => 'B'];
where(['a' => fn ($v) => $v == 'A'], $a); // true
whereAny
whereAny(array $spec, ?iterable $record): bool
Checks if $record
satisfies the spec by invoking the $spec
properties with the corresponding properties of $record
. Returns true
if at least one of the predicates returns true
.
Arguments
- $spec
- [string => ($value): bool]
Example
$objects = [
[ 'a' => 2, 'b' => 1 ],
[ 'a' => 1, 'b' => 2 ]
];
$pred = whereAny([
'a' => gt(_, 10),
'b' => lt(_, 2)
]);
filter($pred, $objects); // [[ 'a' => 2, 'b' => 1 ]]
whereEq
whereEq(array $spec, ?iterable $test): bool
Check if the $test
satisfies the $spec
Example
$pred = whereEq(['a' => 1, 'b' => 2]);
$pred(['a' => 1])); // false
$pred(['a' => 1, 'b' => 2])); // true
$pred(['a' => 1, 'b' => 2, 'c' => 3])); // true
$pred(['a' => 1, 'b' => 1])); // false