Skip to content

Instantly share code, notes, and snippets.

@jcartledge
Created July 22, 2013 23:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcartledge/6058629 to your computer and use it in GitHub Desktop.
Save jcartledge/6058629 to your computer and use it in GitHub Desktop.
Partial application and function composition in PHP.
<?php
/**
* Decorate a function so it can be partially applied.
*
* If the resulting function is called with fewer than the required
* number of arguments a new function is returned with the supplied
* arguments applied.
*
* See examples below.
*
* @param function $fn the function to be decorated.
* @return function the decorated function.
*/
function auto_partial($fn) {
$outer_args = func_get_args();
$fn = array_shift($outer_args);
if(!is_a($fn, 'ReflectionFunction')) $fn = new ReflectionFunction($fn);
return count($outer_args) >= $fn->getNumberOfRequiredParameters() ?
$fn->invokeArgs($outer_args) :
function() use ($fn, $outer_args) {
return call_user_func_array(
'auto_partial',
array_merge(array($fn), $outer_args, func_get_args()));
};
}
$map = auto_partial(function($fn, $arr) {
return array_map($fn, $arr);
});
$filter = auto_partial(function($fn, $arr) {
return array_filter($arr, $fn);
});
$foldl = auto_partial(function($fn, $arr, $init) {
return array_reduce($arr, $fn, $init);
});
$foldr = auto_partial(function($fn, $arr) use ($foldl) {
return $foldl($fn, array_reverse($arr));
});
$compose = function() use ($foldr) {
return $foldr(function($init, $fn) {
return $fn($init);
}, func_get_args());
};
$mod = auto_partial(function($div, $num) { return $num % $div; });
$odd_nums_in = $filter($mod(2));
$squares = $map(function($x) { return $x * $x; });
$odd_nums_in_squares = $compose($odd_nums_in, $squares);
print_r($odd_nums_in_squares(range(1, 100)));
// > Array
// > (
// > [0] => 1
// > [2] => 9
// > [4] => 25
// > [6] => 49
// > [8] => 81
// > [10] => 121
// > [12] => 169
// > [14] => 225
// > [16] => 289
// > [18] => 361
// > [20] => 441
// > [22] => 529
// > [24] => 625
// > [26] => 729
// > [28] => 841
// > [30] => 961
// > [32] => 1089
// > [34] => 1225
// > [36] => 1369
// > [38] => 1521
// > [40] => 1681
// > [42] => 1849
// > [44] => 2025
// > [46] => 2209
// > [48] => 2401
// > [50] => 2601
// > [52] => 2809
// > [54] => 3025
// > [56] => 3249
// > [58] => 3481
// > [60] => 3721
// > [62] => 3969
// > [64] => 4225
// > [66] => 4489
// > [68] => 4761
// > [70] => 5041
// > [72] => 5329
// > [74] => 5625
// > [76] => 5929
// > [78] => 6241
// > [80] => 6561
// > [82] => 6889
// > [84] => 7225
// > [86] => 7569
// > [88] => 7921
// > [90] => 8281
// > [92] => 8649
// > [94] => 9025
// > [96] => 9409
// > [98] => 9801
// > )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment