Function Composition

I am currently reading Simon Holywell’s Functional Programming in PHP, and it talks a little about composing functions. If you’re not familiar with the term; composing functions means combining multiple functions into more complex functions:

$length = function($text) {
return strlen($text);
};

$obscure = function($length) {
return str_repeat("*", $length);
};

$compose = function($a, $b) {
return function() use ($a, $b) {
$arguments = func_get_args();
return $b(call_user_func_array($a, $arguments));
};
};

$replace = $compose($length, $obscure);

print $replace("password"); // "********"
Assigning callbacks to variables is the style which the book uses. I have intentionally kept to this, so please try not to be distracted if you happen to favour a different style.

The idea is that two methods can be combined so that the output of the first will be given as the input to the second. The result will be the output of the second callback. It got me thinking though…

Surely I’m not the first person to wonder what code would be required to chain more than two callbacks? Perhaps something resembling the following:

$reduce = function($result, $item) {
return !is_array($result)
? call_user_func_array($item, [$result])
: call_user_func_array($item, $result)
;
};

$compose = function() use ($reduce) {
$callbacks = func_get_args();

return function() use ($callbacks, $reduce) {
$arguments = func_get_args();

return array_reduce($callbacks, $reduce, $arguments);
};
};

We can confirm that this new $compose function behaves like the previous one:

$replace = $compose($length, $obscure, $length, $obscure);
print $replace("hello world"); // "***********"

Furthermore, we can see a benefit to how the reduced callbacks are invoked:

$join = function() {
return join(" ", func_get_args());
};

$flip = function($a, $b) {
return [$b, $a];
};

$double = $compose($flip, $join);

print $double("hello", "world"); // "world hello"

In this instance, the arity of the callbacks differ, yet the arguments are always passed in an acceptable form. A function returning a single value will be treated as if it returned an array containing that single item.

The $join method is an example of partial function application, but this concept works just as well with currying. There are a few libraries the book recommends for this; namely https://github.com/nicmart/Functionals and https://github.com/Elfet/Functional.

You can get the book from http://www.phparch.com/books/functional-programming-in-php, for $12. It seems useful for beginner to intermediate developers. I have yet to finish it though…

Disclaimer

I bought a copy of this book without being asked to do so by the author or anyone else connected to this book. They don’t yet know I’m writing about or reading it. Surprise!

Show your support

Clapping shows how much you appreciated Christopher Pitt’s story.