Over a million developers have joined DZone.

Reuse your closures with functors

DZone's Guide to

Reuse your closures with functors

· Web Dev Zone
Free Resource

Try RAD Studio for FREE!  It’s the fastest way to develop cross-platform Native Apps with flexible Cloud services and broad IoT connectivity. Start Your Trial Today!

I like PHP closures and their superset, anomyous functions, as they implement the Command pattern very well when used correctly. However I feel that sometimes they are:
  • difficult to reuse: if you want to reuse a closure or anonymous function in two different places, you'll have to share the creation code by putting it in a shared class or method. We have no separation between the creation code (which for an object would be a new operator and the code of the closure itself. It's a bit like eval().
  • Difficult to force contracts on. You can't type hint a closure: even if a closure takes five arguments and another no arguments at all, you can't differentiate between them as parameters in a method signature.
For the latter case, you can just use the undocumented Closure type hint, but it will just catch if an object is passed to the method in question, not if the wrong closure is.
function takesAsInputAnotherFunction(Closure $closure)

This hack is explicitly stated as an implementation detail which should not be relied upon in the PHP manual

__invoke() to the rescue

What if we wanted instead, a closure which we can instance even more than one time (maybe with different variables), and that we could type hint?
In this case, we need to return to the object-oriented paradigm by defining a class, and then use __invoke() to keep the syntactic sugar of being able to call it very simply:

$object($argument1, $argument2);$object($argument1, $argument2);

This kind of object is called a functor.

The definition of a class is longer than the creation code of a closure, so there is a trade-off: we have better specified code but we lose conciseness. Type hints are not only a defensive programming construct: they serve also as documentation as the next programmer reading a method's signature would learn what he can pass in just from the parameters hints instead of going reading the tests or grepping for the method in his working copy:

grep -r '->methodName(' .

becomes just a quick look at the definition

public function methodName(AdderCallback $callback) { // ...

However the expressing power of an object implementing __invoke() and of a closure are equivalent, and when you find yourself rewriting the same closure over and over, you may want to keep it in only one place. You'll have to create a class to hold the creation code anyway, so why not making it a class of its own?

For the PHP interpreter, closure and functors are really the same thing, and are even more swappable than callbacks built with array($object, 'methodName'). is_callable() returns true for both of them, and you can write $closure() as well as $functor().


Here is some code that you can hack if you want to play with closures and functors.

$square = function($value) {
return $value * $value;


* a little more noisy, but equivalent in usage and functionality-
class SquareCallback
public function __invoke($value)
return $value * $value;

$squareObject = new SquareCallback;

// using PHP utilities which works on callback: total equivalency

$array = array(0, 1, 2);
var_dump(array_map($square, $array));
var_dump(array_map($squareObject, $array));

// currying vs collaborators: total equivalency
$toAdd = 5;
$adder = function($value) use ($toAdd) {
return $value + $toAdd;

* A LOT more noisy
class AdderCallback
private $numberToAdd;

public function __construct($numberToAdd)
$this->numberToAdd = $numberToAdd;

public function __invoke($value)
return $value + $this->numberToAdd;
$adder = new AdderCallback(5);

// but only classes can do this
function someMethodOrFunction(AdderCallback $adder)
// ...

Get Your Apps to Customers 5X Faster with RAD Studio. Brought to you in partnership with Embarcadero.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}