Lambda Expressions

Table of Contents

In many programming languages, it can be useful to have a feature that allows the programmer to define a small anonymous function inline that can be treated as a program value, stored into variables and invoked at a later time. Such features go by different names depending on the language, but generally they can all be described using the term "anonymous functions". Typically anonymous functions allow the programmer to capture one or more local variables from the enclosing function body (either implicitly or explicitly), which can be convenient for certain use cases.

In PHP 5.3 the closures feature was introduced, which allowed the programmer to write anonymous functions like so:

1
2
3
4
5
6
7
8
9
10
<?hh
// Example 1
function foo() {
  
$x 'bar';
  return function (
$y) use ($x) {
    return 
$x $y;
  };
}
$fn foo();
echo 
$fn('baz'); // Outputs barbaz

The above example will output:

barbaz

Unfortunately, PHP's closure feature has several shortcomings. First, capturing variables from the enclosing function body is not done implicitly, but rather it requires the programmer to explicitly list which variables should be captured in the "use(..)"clause. Second, even when no variables from the enclosing function body are being captured, the syntax is still relatively verbose compared with anonymous functions in several other languages. Thus while PHP closures help the programmer for some cases, their verbosity makes them more cumbersome to use particularly for design patterns that make heavy use of closures that capture variables and closures nested inside other closures.

To address the shortcomings of PHP closures, HHVM introduced a "lambda expression" feature. Lambda expressions offer similar functionality to PHP closures, but they capture variables from the enclosing function body implicitly and are less verbose in general.

Here are two simple examples of how to use lambda expressions. You can find more examples here.

1
2
3
4
5
6
7
8
9
10
11
12
<?hh
// Never do this, but just illustrating that this won't be captured.
$b 34;
function 
lam(int $b): int {
  
// $b is captured from the parameter in this function body
  
$fn $a ==> $a $b;
  
// Do other stuff
  // .....
  
return $fn(10);
}

var_dump(lam(42)); // return 52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?hh
// Never do this, but just illustrating that this won't be captured.
$b 34;
function 
lam(int $b): int {
  
// Multi-statement lambda body
  // $b is captured from the parameter in this function body
  
$fn $a ==> {$b mult($b); return ($a $b);};
  
// Do other stuff
  // .....
  
return $fn(10);
}

function 
mult(int $x): int {
  return 
$x 4;
}
var_dump(lam(42)); // return 178

Note:

There are currently some limitations to lambda expressions that are being worked on or considered:

  • Lambda expressions don't support capturing variables by reference. If the programmer wants to capture variables by reference, they must use PHP 5.3 closure syntax and put "&" in front of the variable in the "use(..)" list.

  • Lambda expressions don't support returning by reference at present, but support could be added in the future.

To Top