Functional PHP 5.3 Part I - What are Anonymous Functions and Closures?

One of the most exciting features of PHP 5.3 is the first-class support for anonymous functions. You may have heard them referred to as closures or lambdas as well. There‘s a lot of meaning behind these terms so let‘s straighten it all out.

What is the difference between Anonymous Functions, Lambdas, and Closures?

You‘ll see the terms "anonymous functions", "lambdas", and "closures" thrown around in reference to the new features of PHP 5.3. Even the the URLphp.net/closures redirects to php.net/manual/functions.anonymous.php. The difference between ‘lambda‘ and ‘anonymous function‘? None, for all intents and purposes they are two words for the same concept which is a descendant of lambda calculus. Languages with anonymous functions consider functions to be first-class value types, just like integers or booleans. Anonymous functions can thus be passed as arguments to another function or even returned by a function. Let‘s make this concrete in PHP:

  1. <?php  
  2. $lambda = function() {   
  3.             echo "I am an anonymous function,   
  4.                   aka a lambda!<br />";  
  5.             };  
  6. $anonymousFunction = $lambda;  
  7. $anonymousFunction();   
  8. // Output: I am an anonymous function, aka a lambda!  
  9.   
  10. function nCallsTo($n, $function) {  
  11.     for($i = 0; $i < $n; $i++) {  
  12.         $function();  
  13.     }  
  14.     return function() { echo "I am also an anonymous function!<br />"; };  
  15. }  
  16.   
  17. $anotherAnon = nCallsTo(3, $anonymousFunction);  
  18. // Output:  
  19. // I am an anonymous function, aka a lambda!  
  20. // I am an anonymous function, aka a lambda!  
  21. // I am an anonymous function, aka a lambda!  
  22.   
  23. $anotherAnon();  
  24. // Output: I am also an anonymous function!  
  25. ?>  

Notice how we did not assign a name to the function, we assigned a function to be the value of a variable. Just like a string or any other primative. We then assign it to another variable. The function is just a value, it has no name, hence the term "anonymous function". We then create a regular function named nCallsTo that takes two arguments, $n being the number of times to make a call to $function an anonymous function.

The existance of higher-order functions opens the door for techniques likemap/reducenext post.nCallsTo is a higher-order function on two accounts: 1) it takes a function as an argument, and 2) it returns a function as a value. Higher-order functions open the doors for techniques like map/reduce and deserves a post in itself. The point is lambdas and anonymous functions are the same things: functions that are values.

If anonymous functions are values, what does PHP consider their type to be? Let‘s find out:

  1. <?php   
  2. $lambda = function() { echo "anonymous function"; };  
  3. echo gettype($lambda) . ‘<br />‘;  
  4. // Output: object  
  5. echo get_class($lambda) . ‘<br />‘;  
  6. // Output: Closure  
  7. ?>  

On the Closure object in PHP 5.3

What is a closure? So far it‘s a misnomer. We haven‘t actually spotted a closure even though PHP assigns all anonymous functions the type Closure. Since we haven‘t actually seen a closure yet, let‘s take a look at one:

  1. <?php  
  2. function letMeSeeAClosure() {  
  3.     $aLocalNum = 10;  
  4.     return function() use (&$aLocalNum) { return ++$aLocalNum; };  
  5. }  
  6. $aClosure = letMeSeeAClosure();  
  7. echo $aClosure();  
  8. // Output: 11  
  9. echo $aClosure();  
  10. // Output: 12  
  11. $anotherClosure = letMeSeeAClosure();  
  12. echo $anotherClosure();  
  13. // Output: 11  
  14. echo $aClosure();  
  15. // Output: 13  
  16. echo $aLocalNum;  
  17. // Notice: Undefined Variable: aLocalNum<br>?>  

Chew on that for a minute. Do you spot the funny business? $aLocalNum is a local variable defined within the scope of the plain-old function letMeSeeAClosure. With the new use syntax the variable $aLocalNum is bound or closed over to create the closure. This allows the returned Closure to retain a reference to$aLocalNum, even after $aLocalNum falls out of lexical scope when the function returns. The notice error occurs when trying to reference $aLocalNum directly from outside of the function‘s scope.

To recap, the terms, ‘lambda‘ or ‘anonymous function‘ refer to the same concept: functions that are values. Closures refer to a related, but different concept: the lifetime of a variable that is ‘closed over‘, or in PHP 5.3 use‘d, by a closure, is bound to the lifetime, or extent, of the closure. Anonymous functions that are constructed with the use keyword are also closures. As mentioned, in PHP 5.3, anonymous functions are typed as Closure and the three words have, so far, been thrown about. The high-order bit to take away is an understanding that PHP 5.3 now includes language features for anonymous functions and closures.

More on Functional PHP 5.3

If you‘re interested in PHP software development you should subscribe to our feed. Upcoming parts to this series:

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。