On the syntax of closures in PHP

Let me be straight: I find the syntax of anonymous functions and closures in PHP annoying and disturbing. It may be clear and it may be easy to apprehend but it is way too long. Is this a real problem? In my opinion, it is.

Closures are a great weapon for every programmer. They offer a way to encapsulate not only data and states but also common tasks that appear in almost every program, such as filtering, mapping and null checking which I analyze below.

Yet, the syntax of closures is so long, that their application in such tasks make the code longer and less elegant.

In the following examples I am going to use some structures that I won’t define because their implementation is out of the scope of this article. I want to focus on the application of the structures, supposing that somebody has already done the hard work behind the scenes.

Case 1: Filtering

Suppose that you have a list of objects out of which you want to pick those that meet some criteria. Let’s say that your list is $a and you want to pick only the objects whose Name property is equal to $name.

Here is how you would do that in a traditional imperative way:

// PHP imperative way
$result = array();
foreach ($a as $x)
  if ($x->Name == $name)
    $result[] = $x;

Here is how you would go in a functional way (using some smart data structure):

// PHP functional way
$result = $a->Where(
  function($x)use($name){
    return $x->Name == $name;
  });

As you can see the code is not at all shorter, let alone the fact that I had to write $name twice.

Can’t we have something better?  Sure, here is the same code in C#:

// C# functional way
result = a.Where(x => x.Name == name);

Case 2: Mapping

This is a common scenario. From a list of objects $a return a comma separated string of all Names.

// PHP imperative way
$b = array();
foreach ($a as $x)
  $b[] = $x->Name;
$result = implode(', ',$b);

Here is the functional equivalent, again with the help of some data structure:

// PHP functional way
$result = $a->Select(
  function($x){
    return $x->Name;
  })
  ->Join(', ');

Once again this is not shorter or simpler…

Of course, in C#, the same code looks effortless:

// C# functional way
result = a.Select(x => x.Name).Join(', ');

Case 3: Null checking

You know what I am talking about, don’t you? Straight into code:

// PHP imperative way
$result = is_null($x) ? null : $x->Name;

The functional way would imply the use of some Maybe Monad:

// PHP functional way
$result = $x->Select( function($x){ return $x->Name; } );

Once more, this is longer and more complex!

Of course, C# is once again better:

// C# functional way
result = x.Select(x => x.Name);

Conclusion

In all three examples, the functional way has many advantages over the imperative one, because:

  1. The desired behavior is abstracted away and therefore there will be less points of failure.
  2. The result is given from just an expression and not a block of statements. This makes it easier to apply more methods on top of it, in a continuation.
  3. The functional way is lazy.

However, the syntax of PHP’s closures is an obstacle. The programmer is given the choice between simple (but naive) and complex (but state of the art). It does not have to be that way, as C# has shown us!

Anonymous functions and closures have so many applications that I believe a more elegant syntax would benefit everyone.

12 thoughts on “On the syntax of closures in PHP

  1. Case 3 might be better dealt with the shortcut ternary operator in PHP 5.3 and above:

    “Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE, and expr3 otherwise.”

    • I do not like the shortcut ternary operator of PHP because it makes an implicit conversion into boolean. A null value is not necessarily a false value. All implicit conversions of PHP are actually error prone, and here is an example:

      $x = 'A value';
      echo $x ?: 'No value'; // this outputs "A value"

      $x = '0';
      echo $x ?: 'No value'; // this outputs "No value"!!!

      By the way, the short ternary operator cannot even be applied in case 3. We want a value when $x is not null, not when it is. In other worlds, $x ?: $x->Name is not the same as $x ? $x->Name : null, which is applicable but also error prone due to the implicit conversion.

      • But what if you use the identical comparison operators (=== and !==) ?

      • Exactly, I cannot use the identical operators in a short ternary expression! Go ahead and try it. The implicit conversion to boolean is obligatory for the short ternary. In addition your suggestion does not apply here because I want to compare with null and not with false.

  2. I don’t think I would call the Closure implementation an obstacle. It’s perfectly functional; if a bit verbose. PHP has taken the same approach that JavaScript does and uses a very similar syntax; so from my perspective (having done a fair amount of JavaScript as well as PHP) it’s easy to pick up and use.

    Having not written any C#, I can’t really comment on its syntax, but your examples only really cover one use case for closures. If you consider other use cases, such as providing callback functions, the syntax PHP uses is appropriate; for example, you could write something like:

    $log = function($text) { // write log output… };
    $db->setLogCallback($log);
    $db->write(…); // triggers registered log callback

    My point is, the implementation has to be broad enough to cover a large range of use cases, and closure’s have only been available in PHP for a short time. Who knows, down the road we might see some short forms for certain cases (like the shortcut ternary referenced in a previous comment).

    • I agree with you that the current verbose syntax is clear and suitable for callback functions. Actually, C# provides a verbose syntax as well, although I don’t want to stay at what C# does but at what PHP does not.

      Of all callback functions there is one category of functions that consist of exactly one statement. The statement is always a return statement. Also, they usually have one argument (although this is not always the case). Anyway, this special category is proven to be very useful for a variety of tasks (I have given just three examples in the article).

      Unlike your example, this category of functions I am talking about, are functions in the mathematical sense. They map an input to an output and for a given input they always return the same output. The log writing callback you have given is an example of event driven programming, so it belongs to another category. My cases where examples of functional programming. A shorter syntax for these cases opens the door to an entire new world! 🙂

    • In this article I compare syntaxes and not performance. I believe that the lazy evaluation does have performance bonuses but this is something that can be achieved either with the long or with the short syntax, so it is irrelevant to the article.

      • Thanks Linepogl… recently in one JS article I saw we can achieve some performance gain by adopting or following some syntax over the other… so I was just trying to generalize with different scripting languages.. I know JS is client side and PHP is server-side… just a matter of curiosity…. Once again thanks 🙂 …..

  3. Pingback: On the syntax of closures in PHP, part 2 | Le programmeur nomade

  4. Pingback: Short closures for PHP: An implementation | Le programmeur nomade

Leave a reply to justjohn Cancel reply