Lambdas: Introduction

Hack supports the creation of closures through a construct called lambda. Lambdas are generally less verbose than PHP closures and are often used in conjunction with functions like array_filter() or array_map().

Syntax

A lambda is introduced by the lambada operator ==>. To the left of ==> is the list of arguments to the closure. To the right, is an expression or list of statements enclosed by braces {}. See lambda design for more information.

Difference From Traditional Closures

This example shows you how to make use of the shorter lambda syntax. It also uses a Vector, which is one of Hack's collection classes.

<?hh

namespace Hack\UserDocumentation\Lambdas\Examples\Examples\Introduction;

function addLastname(): Vector<string> {
  $people = Vector {
      "Carlton",
      "Will",
      "Phil"
  };
  return $people->map($name ==> $name . " Banks");
}

function run(): void {
  var_dump(addLastname());
}

run();
Output
object(HH\Vector)#3 (3) {
  [0]=>
  string(13) "Carlton Banks"
  [1]=>
  string(10) "Will Banks"
  [2]=>
  string(10) "Phil Banks"
}

The above example is equivalent to the example below using PHP's traditional syntax for anonymous functions. You should see that lambdas make the code more readable and shorter.

<?hh

namespace Hack\UserDocumentation\Lambdas\Examples\Examples\Difference;

function addLastnameTraditional(): array<string> {
  $people = array(
    "Carlton",
    "Will",
    "Phil"
  );
  return array_map(function ($name) {
    return $name . " Banks";
  }, $people);
}

function run(): void {
  var_dump(addLastnameTraditional());
}

run();
Output
array(3) {
  [0]=>
  string(13) "Carlton Banks"
  [1]=>
  string(10) "Will Banks"
  [2]=>
  string(10) "Phil Banks"
}

Essentially, the function ($name) and return from the traditional closure was replaced with the much shorter $name ==>.

Capturing variables

PHP provides the keyword use to capture variables from the enclosing scope. Hack's lambdas make this even easier. You can use variables implicitly inside of a lambda.

<?hh

namespace Hack\UserDocumentation\Lambdas\Examples\Examples\CaptureVariables;

function addLastname(string $lastname): Vector<string> {
  $people = Vector {
      "Carlton",
      "Will",
      "Phil"
  };
  return $people->map($name ==> $name . " " . $lastname);
}

function addLastnameTraditional(string $lastname): array<string> {
  $people = array(
      "Carlton",
      "Will",
      "Phil"
  );
  return array_map(function ($name) use ($lastname) {
    return $name . " " . $lastname;
  }, $people);
}

function run(): void {
  var_dump(addLastnameTraditional("Smith"));
  var_dump(addLastname("Smith"));
}

run();
Output
array(3) {
  [0]=>
  string(13) "Carlton Smith"
  [1]=>
  string(10) "Will Smith"
  [2]=>
  string(10) "Phil Smith"
}
object(HH\Vector)#8 (3) {
  [0]=>
  string(13) "Carlton Smith"
  [1]=>
  string(10) "Will Smith"
  [2]=>
  string(10) "Phil Smith"
}

Notice in addLastName() we are using the passed in parameter $lastname directly within the lambda whereas in addLastNameTraditional, the parameter $lastName must be explicitly captured and called out in a use.

NOTE: All captured variables are captured by value; capturing by reference is not supported. If you need to capture by reference, use a full PHP closure.