Function that do nothing.
noop(); // nothing happen
noop('some string'); // nothing happen
Return the parameter supplied to it.
identity(1); // 1
$obj = new \stdClass;
identity($obj) === $obj; // true
Always return true
.
T(); // true
Always return false
.
F(); // false
Always return null
.
N(); // null
Runs PHP comparison operator ==
.
eq(1, 1); // true
eq(1, '1'); // true
eq(1, 2); // false
Runs PHP comparison operator ===
.
identical(1, 1); // true
identical(1, '1'); // false
Returns true if the first argument is less than the second; false otherwise.
lt(2, 1); // false
lt(2, 2); // false
lt(2, 3); // true
lt('a', 'z'); // true
lt('z', 'a'); // false
Returns true if the first argument is less than or equal to the second; false otherwise.
lte(2, 1); // false
lte(2, 2); // true
lte(2, 3); // true
lte('a', 'z'); // true
lte('z', 'a'); // false
Returns true if the first argument is greater than the second; false otherwise.
gt(2, 1); // true
gt(2, 2); // false
gt(2, 3); // false
gt('a', 'z'); // false
gt('z', 'a'); // true
Returns true if the first argument is greater than or equal to the second; false otherwise.
gte(2, 1); // true
gte(2, 2); // true
gte(2, 3); // false
gte('a', 'z'); // false
gte('z', 'a'); // true
Decorates given function with tail recursion optimization using trampoline.
$fact = tail_recursion(function ($n, $acc = 1) use (&$fact) {
if ($n == 0) {
return $acc;
}
return $fact($n - 1, $acc$n);
});
$fact(10); // 3628800
Returns the !
of its argument.
not(true); // false
not(false); // true
not(0); // true
not(1); // false
Logical negation of the given function $f
.
$notString = complement('is_string');
$notString(1); // true
Call the given function with the given value, then return the value.
$input = new \stdClass();
$input->property = 'foo';
tap(function ($o) {
$o->property = 'bar';
}, $input);
$input->property; // 'foo'
// Also, this function useful as a debug in the `pipe`.
pipe(
'strrev',
tap('var_dump'),
concat('Basko ')
)('avalS'); //string(5) "Slava"
Wrap value within a function, which will return it, without any modifications. Kinda constant function.
$constA = always('a');
$constA(); // 'a'
$constA(); // 'a'
Returns new function which applies each given function to the result of another from right to left.
compose(f, g, h)
is the same as f(g(h(x)))
.
Note: Lenses don't compose backwards https://www.reddit.com/r/haskell/comments/23x3f3/lenses_dont_compose_backwards/
$powerPlus1 = compose(plus(1), power);
$powerPlus1(3); // 10
Performs left to right function composition.
pipe(f, g, h)
is the same as h(g(f(x)))
.
$plus1AndPower = pipe(plus(1), power);
$plus1AndPower(3); // 16
Accepts a converging function and a list of branching functions and returns a new function.
The results of each branching function are passed as arguments to the converging function to produce the return value.
function div($dividend, $divisor) {
return $dividend / $divisor;
}
$average = converge(div, ['array_sum', 'count']);
$average([1, 2, 3, 4]); // 2.5
Alias for call_user_func
.
Alias for call_user_func_array
.
Create a function that will pass arguments to a given function.
$fiveAndThree = apply_to([5, 3]);
$fiveAndThree(sum); // 8
Performs an operation checking for the given conditions.
Returns a new function that behaves like a match operator. Encapsulates if/elseif,elseif, ...
logic.
$cond = cond([
[eq(0), always('water freezes')],
[partial_r(gte, 100), always('water boils')],
[T, function ($t) {
return "nothing special happens at $t °C";
}],
]);
$cond(0); // 'water freezes'
$cond(100); // 'water boils'
$cond(50) // 'nothing special happens at 50 °C'
Returns function which accepts arguments in the reversed order.
Note, that you cannot use curry on a flipped function.
curry
uses reflection to get the number of function arguments,
but this is not possible on the function returned from flip. Instead, use curry_n
on flipped functions.
$mergeStrings = function ($head, $tail) {
return $head . $tail;
};
$flippedMergeStrings = flipped($mergeStrings);
$flippedMergeStrings('two', 'one'); // 'onetwo'
Returns function which accepts two arguments in the reversed order.
$gt9 = flip(gt)(9);
$gt9(10); // true
$gt9(7); // false
Takes a binary function $f
, and unary function $g
, and two values. Applies $g
to each value,
then applies the result of each to $f
.
Also known as the P combinator.
$containsInsensitive = on(contains, 'strtolower');
$containsInsensitive('o', 'FOO'); // true
Accepts function $f
that isn't recursive and returns function $g
which is recursive.
Also known as the Y combinator.
function factorial($n) {
return ($n <= 1) ? 1 : $nfactorial($n - 1);
}
echo factorial(5); // 120, no problem here
$factorial = function ($n) {
return ($n <= 1) ? 1 : $ncall_user_func(__FUNCTION__, $n - 1);
};
echo $factorial(5); // Exception will be thrown
// You can't call anonymous function recursively. But you can use `y` to make it possible.
$factorial = y(function ($fact) {
return function ($n) use ($fact) {
return ($n <= 1) ? 1 : $n$fact($n - 1);
};
});
echo $factorial(5); // 120
Acts as the boolean and
statement.
both(T(), T()); // true
both(F(), T()); // false
$between6And9 = both(flip(gt)(6), flip(lt)(9));
$between6And9(7); // true
$between6And9(10); // false
Takes a list of predicates and returns a predicate that returns true for a given list of arguments if every one of the provided predicates is satisfied by those arguments.
$isQueen = pipe(prop('rank'), eq('Q'));
$isSpade = pipe(prop('suit'), eq('♠︎'));
$isQueenOfSpades = all_pass([$isQueen, $isSpade]);
$isQueenOfSpades(['rank' => 'Q', 'suit' => '♣︎']); // false
$isQueenOfSpades(['rank' => 'Q', 'suit' => '♠︎']); // true
Takes a list of predicates and returns a predicate that returns true for a given list of arguments if at least one of the provided predicates is satisfied by those arguments.
$isClub = pipe(prop('suit'), eq('♣'));
$isSpade = pipe(prop('suit'), eq('♠'));
$isBlackCard = any_pass([$isClub, $isSpade]);
$isBlackCard(['rank' => '10', 'suit' => '♣']); // true
$isBlackCard(['rank' => 'Q', 'suit' => '♠']); // true
$isBlackCard(['rank' => 'Q', 'suit' => '♦']); // false
Applies a list of functions to a list of values.
ap([multiply(2), plus(3)], [1,2,3]); // [2, 4, 6, 4, 5, 6]
Lift a function so that it accepts Monad
as parameters. Lifted function returns Monad
.
Create memoized versions of $f
function.
Note that memoization is safe for pure functions only. For a function to be pure it should:
- Have no side effects
- Given the same arguments it should always return the same result
Memoizing an impure function will lead to all kinds of hard to debug issues.
In particular, the function to be memoized should never rely on a state of a mutable object. Only immutable objects are safe.
$randAndSalt = function ($salt) {
return rand(1, 100) . $salt;
};
$memoizedRandAndSalt = memoized($randAndSalt);
$memoizedRandAndSalt('x'); // 42x
$memoizedRandAndSalt('x'); // 42x
Return number of function arguments.
count_args('explode'); // 3
Return a version of the given function where the $count first arguments are curryied.
No check is made to verify that the given argument count is either too low or too high. If you give a smaller number you will have an error when calling the given function. If you give a higher number, arguments will simply be ignored.
Return a curried version of the given function. You can decide if you also want to curry optional parameters or not.
function add($a, $b, $c) {
return $a + $b + $c;
};
$curryiedAdd = curry('add');
$curryiedAdd(1, 2, 3); // 6
$curryiedAdd(1)(2)(3); // 6
$curryiedAdd(1)(2, 3); // 6
$curryiedAdd(1, 2)(3); // 6
Creates a thunk out of a function. A thunk delays calculation until its result is needed, providing lazy evaluation of arguments.
$add = function($a, $b) {
return $a + $b;
};
$curryiedAdd = thunkify($add);
$addTen = $curryiedAdd(10);
$eleven = $addTen(1);
$eleven(); // 11
Return function $f
that will be called only with abs($count)
arguments,
taken either from the left or right depending on the sign.
$f = static function ($a = 0, $b = 0, $c = 0) {
return $a + $b + $c;
};
ary($f, 2)([5, 5]); // 10
ary($f, 1)([5, 5]); // 5
ary($f, -1)([5, 6]); // 6
Wraps a function of any arity (including nullary) in a function that accepts exactly 1 parameter. Any extraneous parameters will not be passed to the supplied function.
$f = static function ($a = '', $b = '', $c = '') {
return $a . $b . $c;
};
unary($f)(['one', 'two', 'three']); // one
Wraps a function of any arity (including nullary) in a function that accepts exactly 2 parameters. Any extraneous parameters will not be passed to the supplied function.
$f = static function ($a = '', $b = '', $c = '') {
return $a . $b . $c;
};
binary($f)('one', 'two', 'three'); // onetwo
Wraps a function of any arity (including nullary) in a function that accepts exactly 0 parameters. Any extraneous parameters will not be passed to the supplied function.
$f = static function () {
if (func_num_args() > 0) {
throw new \Exception('No arguments expected');
}
return 'ok';
};
$f(); // 'ok'
$f('string'); // 'ok'
$f(1); // 'ok'
$f(1, 'string'); // 'ok'
Produces a new list of elements by mapping each element in list through a transformation function.
Function arguments will be element
, index
, list
.
map(plus(1), [1, 2, 3]); // [2, 3, 4]
flat_map
works applying $f
that returns a sequence for each element in a list,
and flattening the results into the resulting array.
flat_map($data)
differs from flatten(map($data))
because it only flattens one level of nesting,
whereas flatten will recursively flatten nested collections. Indexes will not preserve.
$items = [
[
'id' => 1,
'type' => 'train',
'users' => [
['id' => 1, 'name' => 'Jimmy Page'],
['id' => 5, 'name' => 'Roy Harper'],
],
],
[
'id' => 421,
'type' => 'hotel',
'users' => [
['id' => 1, 'name' => 'Jimmy Page'],
['id' => 2, 'name' => 'Robert Plant'],
],
],
];
$result = flat_map(prop('users'), $items);
//$result is [
// ['id' => 1, 'name' => 'Jimmy Page'],
// ['id' => 5, 'name' => 'Roy Harper'],
// ['id' => 1, 'name' => 'Jimmy Page'],
// ['id' => 2, 'name' => 'Robert Plant'],
//];
Calls $f
on each element in list. Returns origin $list
.
Function arguments will be element
, index
, list
.
each(unary('print_r'), [1, 2, 3]); // Print: 123
Applies a function to each element in the list and reduces it to a single value.
fold(concat, '4', [5, 1]); // 451
function sc($a, $b)
{
return "($a+$b)";
}
fold('sc', '0', range(1, 13)); // (((((((((((((0+1)+2)+3)+4)+5)+6)+7)+8)+9)+10)+11)+12)+13)
The same as fold
but accumulator on the right.
fold_r(concat, '4', [5, 1]); // 514
function sc($a, $b)
{
return "($a+$b)";
}
fold_r('sc', '0', range(1, 13)); // (1+(2+(3+(4+(5+(6+(7+(8+(9+(10+(11+(12+(13+0)))))))))))))
Returns a new list containing the contents of the given list, followed by the given element.
append('three', ['one', 'two']); // ['one', 'two', 'three']
Returns a new list with the given element at the front, followed by the contents of the list.
prepend('three', ['one', 'two']); // ['three', 'one', 'two']
Extract a property from a list of objects.
pluck('qty', [['qty' => 2], ['qty' => 1]]); // [2, 1]
Looks through each element in the list, returning the first one.
head([
['name' => 'jack', 'score' => 1],
['name' => 'mark', 'score' => 9],
['name' => 'john', 'score' => 1],
]); // ['name' => 'jack', 'score' => 1]
Looks through each element in the list, returning the first one that passes a truthy test (function). The
function returns as soon as it finds an acceptable element, and doesn't traverse the entire list. Function
arguments will be element
, index
, list
Returns all items from $list
except first element (head). Preserves $list
keys.
tail([
['name' => 'jack', 'score' => 1],
['name' => 'mark', 'score' => 9],
['name' => 'john', 'score' => 1],
]); // [1 => ['name' => 'mark', 'score' => 9], 2 => ['name' => 'john', 'score' => 1]]
Returns all items from $list
except first element (head) if $f
returns true. Preserves $list
keys.
Can be considered as tail
+ select
.
tail_by(f\compose(gt(8), prop('score')), [
['name' => 'jack', 'score' => 1],
['name' => 'mark', 'score' => 9],
['name' => 'john', 'score' => 1],
]); // [1 => ['name' => 'mark', 'score' => 9]]
Looks through each element in the list, returning an array of all the elements that pass a test (function).
Opposite is reject()
. Function arguments will be element
, index
, list
.
$activeUsers = select(invoker('isActive'), [$user1, $user2, $user3]);
Returns the elements in list without the elements that the test (function) passes.
The opposite of select()
. Function arguments will be element
, index
, list
.
$inactiveUsers = reject(invoker('isActive'), [$user1, $user2, $user3]);
Returns true if the list contains the given value. If the third parameter is true values will be compared in strict mode.
contains('foo', ['foo', 'bar']); // true
contains('foo', 'foo and bar'); // true
Creates a slice of $list
with $count
elements taken from the beginning. If the list has less than $count
,
the whole list will be returned as an array.
For strings its works like substr
.
take(2, [1, 2, 3]); // [0 => 1, 1 => 2]
take(4, 'Slava'); // 'Slav'
Creates a slice of $list
with $count
elements taken from the end. If the list has less than $count
,
the whole list will be returned as an array.
For strings its works like substr
.
take_r(2, [1, 2, 3]); // [1 => 2, 2 => 3]
take_r(4, 'Slava'); // 'lava'
Return N-th element of an array or string.
First element is first, but not zero. So you need to write nth(1, ['one', 'two']); // one
if you want first item.
Consider $elementNumber
as a position but not index.
nth(1, ['foo', 'bar', 'baz', 'qwe']); // 'foo'
nth(-1, ['foo', 'bar', 'baz', 'qwe']); // 'qwe'
nth(1, 'Slava'); // 'S'
nth(-2, 'Slava'); // 'v'
Groups a list by index returned by $f
function.
group(prop('type'), [
[
'name' => 'john',
'type' => 'admin'
],
[
'name' => 'mark',
'type' => 'user'
],
[
'name' => 'bill',
'type' => 'user'
],
[
'name' => 'jack',
'type' => 'anonymous'
],
]); // ['admin' => [...], 'user' => [...], 'anonymous' => [...]]
Partitions a list by function predicate results. Returns an array of partition arrays, one for each predicate, and one for elements which don't pass any predicate. Elements are placed in the partition for the first predicate they pass.
Elements are not re-ordered and have the same index they had in the original array.
list($best, $good_students, $others) = partition(
[
compose(partial_r(gte, 9), prop('score')),
compose(both(partial_r(gte, 6), partial_r(lt, 9)), prop('score'))
],
$students
);
Takes a nested combination of list and returns their contents as a single, flat list.
flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
flatten([1 => 1, 'foo' => '2', 3 => '3', ['foo' => 5]]); // [1, "2", "3", 5]
Takes a nested combination of list and returns their contents as a single, flat list.
Keys concatenated by .
and element index.
flatten_with_keys([
'title' => 'Some title',
'body' => 'content',
'comments' => [
[
'author' => 'user1',
'body' => 'comment body 1'
],
[
'author' => 'user2',
'body' => 'comment body 2'
]
]
]);
// [
// 'title' => 'Some title',
// 'body' => 'content',
// 'comments.0.author' => 'user1',
// 'comments.0.body' => 'comment body 1',
// 'comments.1.author' => 'user2',
// 'comments.1.body' => 'comment body 2',
// ]
Insert a given value between each element of a collection. Indexes are not preserved.
intersperse('a', ['b', 'n', 'n', 's']); // ['b', 'a', 'n', 'a', 'n', 'a', 's']
Sorts a list with a user-defined function.
sort(binary('strcmp'), ['cat', 'bear', 'aardvark'])); // [2 => 'aardvark', 1 => 'bear', 0 => 'cat']
Makes a comparator function out of a function that reports whether the first element is less than the second.
$ar = [1, 1, 2, 3, 5, 8];
usort($ar, comparator(function ($a, $b) {
return $a < $b;
})); // $ar = [1, 1, 2, 3, 5, 8]
sort(
comparator(function ($a, $b) {
return prop('age', $a) < prop('age', $b);
}),
[
['name' => 'Emma', 'age' => 70],
['name' => 'Peter', 'age' => 78],
['name' => 'Mikhail', 'age' => 62],
]
); // [['name' => 'Mikhail', 'age' => 62], ['name' => 'Emma', 'age' => 70], ['name' => 'Peter', 'age' => 78]]
Makes an ascending comparator function out of a function that returns a value that can be compared with <
and >
.
sort(ascend(prop('age')), [
['name' => 'Emma', 'age' => 70],
['name' => 'Peter', 'age' => 78],
['name' => 'Mikhail', 'age' => 62],
]); // [['name' => 'Mikhail', 'age' => 62], ['name' => 'Emma', 'age' => 70], ['name' => 'Peter', 'age' => 78]]
Makes a descending comparator function out of a function that returns a value that can be compared with <
and >
.
sort(descend(prop('age')), [
['name' => 'Emma', 'age' => 70],
['name' => 'Peter', 'age' => 78],
['name' => 'Mikhail', 'age' => 62],
]); // [['name' => 'Peter', 'age' => 78], ['name' => 'Emma', 'age' => 70], ['name' => 'Mikhail', 'age' => 62]]
Returns a new list containing only one copy of each element in the original list, based upon the value returned by applying the supplied function to each list element. Prefers the first item if the supplied function produces the same value on two items.
uniq_by('abs', [-1, -5, 2, 10, 1, 2]); // [-1, -5, 2, 10]
Returns a new list containing only one copy of each element in the original list.
uniq([1, 1, 2, 1]); // [1, 2]
uniq([1, '1']); // [1, '1']
Zips two or more sequences.
Note: This function is not curried because of no fixed arity.
zip([1, 2], ['a', 'b']); // [[1, 'a'], [2, 'b']]
Zips two or more sequences with given function $f
.
As a result: zip_with(plus, [1, 2], [3, 4])
equals to plus([$arg1, $arg2])
.
But zip_with(call(plus), [1, 2], [3, 4])
equals to plus($arg1, $arg2)
.
Note: This function is not curried because of no fixed arity.
zip_with(call(plus), [1, 2], [3, 4]); // [4, 6]
Returns all possible permutations.
permute(['a', 'b']); // [['a', 'b'], ['b', 'a']]
Check if number is even.
is_even(4); // true
is_even(3); // false
Check if number is odd.
is_odd(5); // true
is_odd(2); // false
Increments its argument.
inc(41); // 42
Decrements its argument.
dec(43); // 42
Perform $a + $b
.
plus(4, 2); // 6
Perform $a - $b
.
minus(4, 2); // 2
Perform $a / $b
.
div(4, 2); // 2
Modulo of two numbers.
modulo(1089, 37)); // 16
Perform $a$b
.
multiply(4, 2); // 8
Fold list with plus
.
sum([3, 2, 1]); // 6
Fold list with minus
.
diff([10, 2, 1]); // 7
Fold list with div
.
divide([20, 2, 2]); // 5
Fold list with multiply
.
product([4, 2, 2]); // 16
Calculate average value.
average([1, 2, 3, 4, 5, 6, 7]); // 4
Power its argument.
power(4); // 16
Calculate median.
median([2, 9, 7]); // 7
median([7, 2, 10, 9]); // 8
Restricts a value to be within a range.
clamp(1, 10, -5); // 1
clamp(1, 10, 15); // 10
clamp(1, 10, 4); // 4
clamp('2023-01-01', '2023-11-22', '2012-11-22'); // 2023-01-01
clamp('2023-01-01', '2023-11-22', '2023-04-22'); // 2023-04-22
// Example:
$pagePortion = clamp(MIN_PORTION, MAX_PORTION, $_REQUEST['perPage']);
Cartesian product of sets. X = {1, 2} Y = {a, b} Z = {A, B, C} X × Y × Z = { (1, a, A), (2, a, A), (1, b, A), (2, b, A) (1, a, B), (2, a, B), (1, b, B), (2, b, B) (1, a, C), (2, a, C), (1, b, C), (2, b, C) }
Note: This function is not curried because of no fixed arity.
$ranks = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'Jack', 'Queen', 'King', 'Ace'];
$suits = ["Hearts", "Diamonds", "Clubs", "Spades"];
$cards = pipe(cartesian_product, map(join('')))($ranks, [' of '], $suits);
// [
// '2 of Hearts',
// '2 of Diamonds',
// ...
// 'Ace of Clubs',
// 'Ace of Spades',
// ];
Returns new function which will behave like $f
with
predefined left arguments passed to partial.
$implode_coma = partial('implode', ',');
$implode_coma([1, 2]); // 1,2
Returns new partial function which will behave like $f
with
predefined right arguments passed to rpartial.
$implode12 = partial_r('implode', [1, 2]);
$implode12(','); // 1,2
Returns new partial function which will behave like $f
with
predefined positional arguments passed to ppartial.
$sub_abcdef_from = partial_p('substr', [
1 => 'abcdef',
3 => 2
]);
$sub_abcdef_from(0); // 'ab'
Returns a lens for the given getter and setter functions. The getter "gets" the value of the focus; the setter "sets" the value of the focus.
$xLens = lens(prop('x'), assoc('x'));
view($xLens, ['x' => 1, 'y' => 2]); // 1
set($xLens, 4, ['x' => 1, 'y' => 2]); // ['x' => 4, 'y' => 2]
over($xLens, dec, ['x' => 1, 'y' => 2]); // ['x' => 0, 'y' => 2]
Returns a "view" of the given data structure, determined by the given lens.
$xLens = lens_prop('x');
view($xLens, ['x' => 1, 'y' => 2]); // 1
view($xLens, ['x' => 4, 'y' => 2]); // 4
Returns the result of "setting" the portion of the given data structure focused by the given lens to the result of applying the given function to the focused value.
$xLens = lens_prop('x');
over($xLens, plus(100), ['x' => 1, 'y' => 2]); // ['x' => 101, 'y' => 2]
Returns the result of "setting" the portion of the given data structure focused by the given lens to the given value.
$xLens = lens_prop('x');
set($xLens, 4, ['x' => 1, 'y' => 2]); // ['x' => 4, 'y' => 2]
set($xLens, 8, ['x' => 1, 'y' => 2]); // ['x' => 8, 'y' => 2]
Returns a lens whose focus is the specified property.
$xLens = lens_prop('x');
view($xLens, ['x' => 1, 'y' => 2]); // 1
set($xLens, 4, ['x' => 1, 'y' => 2]); // ['x' => 4, 'y' => 2]
over($xLens, dec, ['x' => 1, 'y' => 2]); // ['x' => 0, 'y' => 2]
Returns a lens whose focus is the specified path.
$data = [
'a' => 1,
'b' => [
'c' => 2
],
];
$lens = lens_prop_path(['b', 'c']);
view($lens, $data); // 2
view($lens, set($lens, 4, $data)); // ['a' => 1, 'b' => ['c' => 4]]
view($lens, over($lens, multiply(2), $data)); // ['a' => 1, 'b' => ['c' => 4]]
Returns a lens whose focus is the specified nth
element.
view(lens_element(1), [10, 20, 30]); // 10
view(lens_element(-1), [10, 20, 30]); // 30
set(lens_element(1), 99, [10, 20, 30]); // [99, 20, 30]
Returns arguments as a list.
to_list(1, 2, 3); // [1, 2, 3]
to_list('1, 2, 3'); // [1, 2, 3]
Concatenates $a
with $b
.
concat('foo', 'bar'); // 'foobar'
Concatenates all given arguments.
concat('foo', 'bar', 'baz'); // 'foobarbaz'
Returns a string made by inserting the separator between each element and concatenating all the elements into a single string.
join('|', [1, 2, 3]); // '1|2|3'
Performs an if/else
condition over a value using functions as statements.
$ifFoo = if_else(eq('foo'), always('bar'), always('baz'));
$ifFoo('foo'); // 'bar'
$ifFoo('qux'); // 'baz'
Creates a function that can be used to repeat the execution of $f
.
repeat(thunkify('print_r')('Hello'))(3); // Print 'Hello' 3 times
Takes two functions, a tryer and a catcher. The returned function evaluates the tryer. If it does not throw, it simply returns the result. If the tryer does throw, the returned function evaluates the catcher function and returns its result. For effective composition with this function, both the tryer and catcher functions must return the same type of results.
try_catch(function () {
throw new \Exception();
}, always('val'))(); // 'val'
Returns a function that invokes method $method
with arguments $methodArguments
on the object.
array_filter([$user1, $user2], invoker('isActive')); // only active users
Count length of string or number of elements in the array.
len('foo'); // 3
len(['a', 'b']); // 2
Returns a function that when supplied an object returns the indicated property of that object, if it exists.
prop(0, [99]); // 99
prop('x', ['x' => 100]); // 100
$object = new \stdClass();
$object->x = 101;
prop('x', $object); // 101
Thunkified version of prop
function, for more easily composition with either
for example.
prop_thunk(0, [99])(); // 99
Nested version of prop
function.
prop_path(['b', 'c'], [
'a' => 1,
'b' => [
'c' => 2
],
]); // 2
Acts as multiple prop
: array of keys in, array of values out. Preserves order.
props(['c', 'a', 'b'], ['b' => 2, 'a' => 1]); // [null, 1, 2]
Creates a shallow clone of a list with an overwritten value at a specified index.
assoc('bar', 42, ['foo' => 'foo', 'bar' => 'bar']); // ['foo' => 'foo', 'bar' => 42]
assoc(
'full_name',
compose(join(' '), props(['first_name', 'last_name'])),
[
'first_name' => 'Slava',
'last_name' => 'Basko'
]
); // ['first_name' => 'Slava', 'last_name' => 'Basko', 'full_name' => 'Slava Basko']
Same as assoc
, but it allows to specify element by its number rather than named key.
assoc_element(1, 999, [10, 20, 30]); // [999, 20, 30]
assoc_element(-1, 999, [10, 20, 30]); // [10, 20, 999]
Nested version of assoc
function.
assoc_path(['bar', 'baz'], 42, ['foo' => 'foo', 'bar' => ['baz' => 41]]); // ['foo' => 'foo', 'bar' => ['baz' => 42]]
Returns a function that invokes $method
with arguments $arguments
on the $object.
to_fn($obj, 'someMethod', ['arg'])(); // Equal to $obj->someMethod('arg');
Takes two arguments, $fst
and $snd
, and returns [$fst, $snd]
.
pair('foo', 'bar'); // ['foo', 'bar']
A function wrapping calls to the functions in an ||
operation, returning the result of the first function
if it is truth-y and the result of the next function otherwise.
Note: Will return result of the last function if all fail.
$value = either(prop('prop1'), prop('prop2'), prop('prop3'));
$value([
'prop2' => 'some value'
]); // 'some value'
The same as either
, but returning the result of the first function
if it is not NULL and the result of the next function otherwise.
Note: Will return NULL if all fail.
Quote given string.
quote('foo'); // "foo"
map(quote, ['foo', 'bar']); // ['"foo"', '"bar"']
Same as quote
, but with addslashes
before.
Returns an array only with the specified keys.
only_keys(['bar', 'baz'], ['foo' => 1, 'bar' => 2, 'baz' => 3]); // ['bar' => 2, 'baz' => 3]
Drops specified keys.
omit_keys(['baz'], ['foo' => 1, 'bar' => 2, 'baz' => 3]); // ['foo' => 1, 'bar' => 2]
Applies provided function to specified keys.
map_keys('strtoupper', ['foo'], ['foo' => 'val1', 'bar' => 'val2']); // ['foo' => 'VAL1', 'bar' => 'val2']
Applies provided function to N-th elements of an array.
First element is first, but not zero (similar to nth
function).
map_elements('strtoupper', [1], ['foo' => 'val1', 'bar' => 'val2']); // ['foo' => 'VAL1', 'bar' => 'val2']
Finds if a given array has all of the required keys set.
find_missing_keys(
['login', 'email'],
['login' => 'admin']
); // ['email']
Creates copy of provided value. clone
will be called for objects.
You can overwrite clone
and provide your specific function, just define CLONE_FUNCTION
constant.
$obj = new \stdClass(); // object hash: 00000000000000030000000000000000
cp($obj); // object hash: 00000000000000070000000000000000
Return random value from list.
pick_random_value(['sword', 'gold', 'ring', 'jewel']); // 'gold'
Creates an associative array using a $keyProp
as the path to build its keys,
and $valueProp
as path to get the values.
combine('alpha2', 'name', [
[
'name' => 'Netherlands',
'alpha2' => 'NL',
'alpha3' => 'NLD',
'numeric' => '528',
],
[
'name' => 'Ukraine',
'alpha2' => 'UA',
'alpha3' => 'UKR',
'numeric' => '804',
],
]); // ['NL' => 'Netherlands', 'UA' => 'Ukraine']
Returns an infinite, traversable sequence of constant values.
Returns an infinite, traversable sequence that linearly grows by given amount.
Returns an infinite, traversable sequence that exponentially grows by given percentage.
Returns an infinite, traversable sequence of 0.
This helper mostly to use with retry
.
Retry a function until the number of retries are reached or the function does no longer throw an exception.
retry(3, no_delay, [$db, 'connect']); // Runs `$db->connect()` 3 times without delay (if method throw exception)
retry(3, sequence_linear(1, 5), [$ftp, 'upload']); // Runs `$ftp->upload()` 3 times with a linear back-off
Creates instance of given class.
construct('stdClass'); // object(stdClass)
Creates instance of given class with arguments passed to __construct
method.
$user = construct_with_args(User::class, ['first_name' => 'Slava', 'last_name' => 'Basko']);
echo $user->first_name; // Slava
Swaps the values of keys a
and b
.
flip_values('key1', 'key2', ['key1' => 'val1', 'key2' => 'val2']); // ['key1' => 'val2', 'key2' => 'val1']
Function that helps you determine every Nth iteration of a loop.
$is10thIteration = is_nth(10);
for ($i = 1; $i <= 20; $i++) {
if ($is10thIteration($i)) {
// do something on each 10th iteration (when $i is 10 and 20 in this case)
}
}
Publishes any private method.
class Collection
{
public function filterNumbers(array $collection) {
return select([$this, 'isInt'], $collection); // This will throw an exception
}
private function isInt($n) {
return is_int($n);
}
}
// The above will generate an error because `isInt` is a private method.
// This will work.
public function filterNumbers(array $collection)
{
return select(publish('isInt', $this), $collection);
}
Alias of explode
.
str_split(' ', 'Hello World'); // ['Hello', 'World']
Splits string on 2 parts by X position.
str_split_on(2, 'UA1234567890'); // ['UA', '1234567890']
Alias of native str_replace
.
str_replace(' ', '', 'a b c d e f'); // abcdef
Use partial_p
if you need $count argument:
$f = partial_p('str_replace', [
1 => $search,
2 => $replace,
4 => &$count
]);
The same as str_replace
but replace only first occurrence.
str_replace_first('abc', '123', 'abcdef abcdef abcdef'); // "23def abcdef abcdef
Checks if $string
starts with $token
.
str_starts_with('http://', 'http://gitbub.com'); // true
Checks if $string
ends with $token
.
str_ends_with('.com', 'http://gitbub.com'); // true
Checks if a string matches a regular expression.
$is_numeric = str_test('/^[0-9.]+$/');
$is_numeric('123.43'); // true
$is_numeric('12a3.43'); // false
Alias of str_pad
.
str_pad_left('6', '0', '481'); // 000481
Alias of str_pad
.
str_pad_right('6', '0', '481'); // 481000
Checks if any of the strings in an array $needles
present in $haystack
string.
str_contains_any(['a', 'b', 'c'], 'abc'); // true
str_contains_any(['a', 'b', 'c'], 'a'); // true
str_contains_any(['a', 'b', 'c'], ''); // false
str_contains_any(['a', 'b', 'c'], 'defg'); // false
Checks if all of the strings in an array $needles
present in $haystack
string.
Note: Will return true if $needles
is an empty array.
str_contains_all(['a', 'b', 'c'], 'abc'); // true
str_contains_all(['a', 'b', 'c'], 'cba'); // true
str_contains_all(['a', 'b', 'c'], 'a'); // false
str_contains_all(['a', 'b', 'c'], ''); // false
str_contains_all([], 'abc'); // true
Surrounds a string with a prefix and suffix.
str_surround('(', ')', 'abc'); // (abc)
str_surround('<strong>', '</strong>', 'abc'); // <strong>abc</strong>
Validates that the value is instance of specific class.
is_type_of(\User::class, new User()); // true
is_type_of(\User::class, new SomeClass()); // false
Checks that the value is instance of specific class.
type_of(\User::class, new User()); // User
type_of(\User::class, new SomeClass()); // TypeException: Could not convert "SomeClass" to type "User"
Checks and coerces value to bool
.
type_bool(true); // true
type_bool(1); // true
type_bool('1'); // true
type_bool(false); // false
type_bool(0); // false
type_bool('0'); // false
type_bool('some-string'); // TypeException: Could not convert "string" to type "bool"
Checks and coerces value to string
.
Object: method __toString
will be called
Array: all values will be concatenated with comma.
type_string('hello'); // 'hello'
type_string(123); // '123'
Checks and coerces value to non-empty-string
.
Object: method __toString
will be called
Array: all values will be concatenated with comma.
type_non_empty_string('abc'); // 'abc'
type_non_empty_string([]); // TypeException: Could not convert "array" to type "non-empty-string"
Checks and coerces value to int
.
type_int('123'); // 123
type_int('007'); // 7
type_int('1.0'); // 1
Checks and coerces value to positive_int
.
type_positive_int(2); // 2
type_positive_int('2'); // 2
Checks and coerces value to float
.
type_float(123); // 123.0
type_float('123'); // 123.0
Union type.
$t = type_union(type_int, type_float);
$t(1); // 1;
$t(1.25); // 1.25
$t('1'); // 1
Checks and coerces value to valid array key that can either be an int
or a string
.
type_array_key(1); // 1
type_array_key('some_key'); // some_key
Checks and coerces list values to $type[]
.
type_list(type_int, [1, '2']); // [1, 2]
type_list(type_int, [1, 2.0]); // [1, 2]
type_list(type_of(SomeEntity::class), [$entity1, $entity2]); // [$entity1, $entity2]
Checks and coerces array keys to $keyType
and values to $valueType
.
type_array(type_array_key, type_int, ['one' => '1', 'two' => 2]); // ['one' => 1, 'two' => 2]
Checks array keys presence and coerces values to according types.
All key => value
pair that not described will be removed.
$parcelShape = type_shape([
'description' => type_string,
'value' => type_union(type_int, type_float),
'dimensions' => type_shape([
'width' => type_union(type_int, type_float),
'height' => type_union(type_int, type_float),
]),
'products' => type_list(type_shape([
'description' => type_string,
'qty' => type_int,
'price' => type_union(type_int, type_float),
]))
]);
$parcelShape([
'description' => 'some goods',
'value' => 200,
'dimensions' => [
'width' => 0.1,
'height' => 2.4,
],
'products' => [
[
'description' => 'product 1',
'qty' => 2,
'price' => 50,
],
[
'description' => 'product 2',
'qty' => 2,
'price' => 50,
],
],
'additional' => 'some additional element value that should not present in result'
]); // checked and coerced array will be returned and `additional` will be removed
Makes sense to use in type_shape
.
$typeUser = type_shape([
'name' => type_string,
'lastName' => type_string,
'location' => type_optional(type_string),
]);
$typeUser(['name' => 'Slava', 'lastName' => 'Basko']);
// ['name' => 'Slava', 'lastName' => 'Basko']
$typeUser(['name' => 'Slava', 'lastName' => 'Basko', 'location' => 'Vancouver']);
// ['name' => 'Slava', 'lastName' => 'Basko', 'location' => 'Vancouver']
$typeUser(['name' => 'Slava', 'lastName' => 'Basko', 'location' => function() {}]); // TypeException
Checks if a given value is within a predefined set of values (enumeration).
type_enum(['one', 'two', 'three'], 'one'); // 'one'
type_enum(['one', 'two', 'three'], 'four'); // TypeException: Value "four" is not in enum('one', 'two', 'three')
Race conditions safe file write.
$io = write_file(0666, '/path/to/file.txt', 'content');
$io(); // Content write into file at this moment.
Read file contents.
$io = read_file('/path/to/file.txt');
$content = $io(); // Content read from file at this moment.