Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Closures and lambda functions in PHP vs. JavaScript

with 2 comments

JavaScript and PHP support both lambda functions and closures. But the terms are poorly understood in both programming languages ​​and are often confused with each other.

Lambda functions

Also called anonymous functions. They refer to functions that can be called without being bound to an identifier. One of their purposes is to be passed as arguments. The Lambda name was introduced by Alonzo Church, inventor of lambda calculus in 1936. In lambda calculus all functions are anonymous.

JavaScript

In JavaScript lambdas are part of the standard set and there are the preferred method of defining functions.

For instance:

var add = function (a, b) {
     return a + b;
}
alert(add(1, 2)); // 3

Lambda functions are used almost in any context when it comes to JavaScript, like:

window.onload = function (e) {
     alert('The page has loaded!');
}

PHP

In PHP, lambda functions were introduced in version 4.0.1 using create_function. In version 5.3+ a similar syntax to JavaScript was added, a much more readable and elegant way of defining a function.

This means that in PHP there are two ways of creating a lambda function:

// PHP 4.0.1+
$add = create_function('$a, $b', 'return $a + $b;');

// vs.

// PHP 5.3+
$add = function ($a, $b) {
     return $a + $b;
};

echo $a(1,2); // 3

Lambda functions can be used as parameter for other functions, such as usort:

$array = array(4, 3, 5, 1, 2);
usort($array, function ($a, $b) {
     if ($a == $b) {
          return 0;
     }
     return ($a < $b) ? -1 : 1;
});

Even more, PHP 5.3+ allows calling an object as a anonymous function:

class test {
     function __invoke($a) {
          echo $a;
     }
}
$a = new test();
$a('test'); // 'test'

Closures

The closure is really the misunderstood concept of the two. In general confusion appears because closures may involve lambda functions. A closure refers to the ability of a function/object to access the scope in which it was created even if the parent function has ended it’s execution and returned. In other words, the function/object returned by a closure is running in the scope in which it was defined.

In JavaScript the notion of closure is part of the standard arsenal, because the language is not based on the traditional object model, but rather on prototypes and functions. But JavaScript has some traditional object model parts, like the fact that you can use “new” to construct an object based on a function that plays the role of a class. In PHP closures are more of an new way to approach problems, because PHP is part of the traditional object model family.

JavaScript

In JavaScript the notion of closure is widely used, it’s so popular because JavaScript is not a traditional object orientated language, but rather a functional one, based on prototype inheritance.

JavaScript doesn’t have Public, Private and Protected, but rather only Public and Private and objects an inherit from each other, without using classes.

Another issue is the scope, because the global scope is used by default. This issues can be fixed in an elegant fashion using closures:

var closure = function () {
     var sum = 0;
     return {
          add: function (nr) {
               sum += nr;
          },
          getSum: function () {
               return sum;
          }
     }
}();

closure.add(1);
closure.add(2);
console.log(closure.getSum());

In the example above, sum is a private property and in theory can only be accessed and modified by the closure function. The interesting part is that the parentheses from the end of the function definition, signify that this function will be immediately  executed and therefore will return the result which is an object. At this point the original function will only exist for serving the return object, encapsulating therefor the private variable.

Although the function has finished execution, through this closure the returned object can still access the variables defined in the function scope, because that was the environment in which it was created.

This becomes even more interesting when a function returns another function:

var counter = function () {
    var counter = 0;
    console.log('in closure');
    return function () {
        console.log('in the anonymous function');
        return ++counter;
    };
};
var counter1 = counter();

console.log(counter1()); // 1

var counter2 = counter();
console.log(counter2()); // 1
console.log(counter1()); // 2

The output will be:

in closure
in the anonymous function
1
in closure
in the anonymous function
1
in the anonymous function
2

What actually happens is that the first function is executed and returns an anonymous function that can still access the environment in which it was created. In my opinion this is where the confusion between closures and lambda functions comes from, because a function returns another function.

The difference between examples is that in the first one the closure function executes immediately, and in the second example when counter is executed it’s returning a result that is actually a function definition, which in turn can be executed. Of course the second example can be modified to act just like in the first example using parenthesis.

PHP

As I said above, the notion of closure in PHP is not as important as in JavaScript.

Considering that lambda functions are available in the language since version 4, closures only appeared with PHP 5.3+.

Because of the block scope nature of PHP, there is a better encapsulation but there is a lot less flexibility compared to JavaScript. Basically in PHP you must specify using the use instruction what will the anonymous function be able to access from the closure scope.

function closure () {
     $c = 0;
     return function ($a) use (&$c) {
          $c += $a;
          echo $a . ', ' . $c . PHP_EOL;
     };
}

$closure = closure();

$closure(1);
$closure(2);

Unlike JavaScript, in PHP closures can not return objects, or rather the object can not be bound to the scope in which it was created, unless you send the variables as a reference to the constructor, in which case is not very elegant and I can’t imagine a scenario that would absolutely need closure for this.

Like in the JavaScript examples, instead of parentheses “()” at the end of the function, in PHP to run a function immediately after defining it call_user_func() or call_user_func_array() can be used:

$closure = call_user_func(function () {
    $c = 0;
    return function ($a) use (&$c) {
        $c += $a;
        echo $a . ', ' . $c . PHP_EOL;

    };
});

$closure(1);
$closure(2);

Written by Claudiu Persoiu

16 April 2011 at 6:02 PM

2 Responses to 'Closures and lambda functions in PHP vs. JavaScript'

Subscribe to comments with RSS or TrackBack to 'Closures and lambda functions in PHP vs. JavaScript'.

  1. where you wrote echo $a(1,2); // 3
    I think should be
    echo $add(1,2); // 3

    razvan

    17 April 2011 at 2:21 PM

  2. Yep, my bad! I had renamed the variable along the way but I’ve forgot about that.

    By the way, there is a romanian section too, you got the english version because of your IP. 😉

    admin

    17 April 2011 at 4:59 PM

Leave a Reply