Short closures for PHP: An implementation

In this article, I present an implementation of an alternative short syntax for closures in PHP. I believe it to be an elegant solution and so I have begun writing a proposal for inclusion in the next version of PHP.

What it does

My implementation provides an alternative short syntax for anonymous functions and closures, focusing on those that have a single return statement.

// Current syntax:
$f = function( $x ){ return $x->Name; };
$g = function( $x )use( $y ){ return $x==$y; };

// Proposed alternative syntax:
$f = | $x |=> $x->Name;
$g = | $x : $y |=> $x==$y;

All in all, I have tried to eliminate the syntax noise by reducing the key strokes in the the non-significant parts of the expression:

function(      9 chars --->      |      1 char
)use(          5 chars --->      :      1 char
){return       8 chars --->      |=>    3 chars
;}             2 chars --->             0 chars
              --------                  -------
              24 chars                  5 chars

Advantages (besides less key strokes)

  1. The code is more readable (more on this below).
  2. The syntax is backwards compatible. The short lambda and the longer equivalent are totally interchangeable.
  3. Variable scoping mechanics have not changes at all. There is nothing new here but syntactic sugar.
  4. Lambda expressions are searchable. The |=> operator is unique.
  5. The |=> operator is similar to =>. That’s good because they both relate to mapping. In addition, the : operator is similar to :: and that’s also good because they both relate to scoping.
  6. Although it is not the primary use case, the proposed implementation supports type hinting, passing by reference and return by reference just like the longer alternative. There is also an option to fall back to a statement block if the single return statement is not enough.

Some disadvantages

  1. The short syntax is clear and readable, but can become confusing when used in the wrong places. Yet, isn’t this the case with every feature?
  2. A short lambda without arguments ( ||=>… ) conflicts with the logical or operator ( || ) resulting in a syntax error. A way to avoid this is to insert whitespace between the two pipes, but this breaks the invariant that whitespace is not important in PHP. This is a minor problem and there are ways to deal with it in the compiler level.

Readability

I want to stay on the readability a little bit more, because that was one of the reasons that a similar proposal for a short array syntax has been rejected.

I support that the syntax I propose is not just some Perl-like hocus-pocus to avoid writing some extra bytes of code, but it is actually more readable than the old one. This is because it focuses on what to do and not on how to do it.

Let’s try to translate the above examples in plain English.

function( $x ){ return $x->Name; }

A function that takes an argument $x and returns its name

| $x |=> $x->Name

Given an $x, get its name

How is this different? First of all, because I don’t care whether this is a function or not. All I want is the name of a given $x. Of course, in order to get the name, a callback function is going to be called for the argument $x, but this is just a technical detail that is not the most important thing in my clause.

The same goes for the second example:

function( $x )use( $y ){ return $x==$y; }

A function that takes an argument $x, captures the variable $y and returns weather these two are equal.

| $x : $y |=> $x==$y

Given an $x for the current $y, see weather these two are equal.

A more complicated example

$add = function( $x ){
  return function( $y )use( $x ){
    return $x+$y;
  };
};

A function that takes an argument $x that returns another function that takes an argument $y, captures the first argument $x and returns their sum.

Now, that’s sounds complicated, doesn’t it? But it is not. It is a typical application of currying that you can find in the first pages of any functional programming tutorial. Yet, there is so much syntax noise here that the pattern is hardly visible.

With the new short syntax, the above example could be rewritten like that:

$add = |$x|=> |$y:$x|=> $x+$y;

Given an $x, wait for a $y for this $x, to get their sum.

Anyone with a little exposure to functional languages can immediately recognize the pattern.

Some real world applications

In a recent article, I had presented three cases that could be benefited from a shorter closure syntax. The current syntax is like this:

// Case 1: Filtering (with a LINQ-style Iterator)
$result = $a->Where(
  function($x)use($name){
    return $x->Name == $name;
  });

// Case 2: Mapping (with a LINQ-style Iterator)
$result = $a->Select(
  function($x){
    return $x->Name;
  })
  ->Join(', '); 

// Case 3: Null avoiding (with a a Maybe Monad)
$result = $x->Select( function($x){ return $x->Name; } );

With the new syntax, we can have this code:

// Case 1: Filtering
$result = $a->Where( |$x:$name|=> $x->Name==$name ); 

// Case 2: Mapping
$result = $a->Select( |$x|=>$x->Name )->Join(', ');

// Case 3: Null avoiding
$result = $x->Select( |$x|=>$x->Name );

Conclusion

I believe that PHP’s readability will be improved with the proposed syntax and this is why I will try to convince the developers of PHP to include it in the next version.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s