Funciones anónimas en php

Una de las novedades más interesantes de PHP 5.3 son los dos tipos de funciones anónimas, hasta hace poco no había tenido necesidad de usarlas, pero en un script que he tenido que programar para ejecutar como un demonio he podido aprovechar para usarlas, y la verdad es que en el momento dado pueden ahorrarnos unas cuantas líneas de código, agregar archivos donde guardamos helpers, etc

Pero vamos a ver lo que son, las funciones anónimas como su nombre indican son funciones que no necesitan de un nombre para definirse.

<?php
 
function ($vars) {
   
//Here we have code
 
};
?>



Pero no se puede intentar imprimir directamente la declaración de la función anónima.

<?php
 
print ( function(){
    echo
'hola mundo' . "\r\n";
  });
?>



Este código devuelve

PHP Catchable fatal error:  Object of class Closure could not be converted to string in /....



Estas funciones anónimas se pueden asociar a otras funciones como si fuesen variables.

<?php
 
// Set a multiplier
 
$multiplier = 3;
  
 
// Create a list of numbers
 
$numbers = array(1,2,3,4);
  
 
// Use array_walk to iterate
  // through the list and multiply
 
array_walk($numbers, function($number) use($multiplier){
    echo
$number * $multiplier;
  });
?>



Obviamente, si podemos usarlo como parámetros dentro de otras funciones podemos hacerlo mismo y usarlas como parámetros para métodos de objetos.

También pueden ser guardadas dentro de variables para su posterior uso.

<?php
  $c
= function ($a){ 
    return
$a;
  };
  print
$c('hola mundo');
?>



Una vez visto lo que son las funciones anónimas, y algunos casos de uso, vamos a profundizar en la diferencia entre las lambdas y los Closures.

La diferencia más importante entre ambas es que a los Closures se les puede asignar una o más variables / atributos definidos previamente y que van identificados después de la palabra use

<?php
/**
 * Lambda
 */
$c = function ($a){
  return
$a;
};   

print $c('hola mundo');
//devuelve "hola mundo"

/**
 *Closure
 */
$e = 'Hola';
$f = 'mundo';
$d = function ($g) use ($e, $f){
  return
$e . $f. $g;
}

print $d('¿Qué tal estas?');
// devuelve "Hola mundo ¿Qué tal estas?"
?>



Si hacemos un var_dump de las dos funciones que acabamos de definir comprobamos que nos dan información muy interesante

<?php
var_dump
($c); 
?>


object(Closure)#64 (1) {
  ["parameter"]=>
  array(1) {
    ["$a"]=>
    string(10) ""
  }
}


<?php
var_dump
($d);
?>


object(Closure)#65 (2) {
  ["static"]=>
  array(2) {
    ["e"]=>
    string(7) "wadus t"
    ["f"]=>
    string(7) "wadus f"
  }
  ["parameter"]=>
  array(1) {
    ["$g"]=>
    string(10) ""
  }
}

Se puede comprobar, que las funciones anónimas por debajo funcionan como objetos de tipo Closure, y la diferencia más importante entre ambas es que el atributo de los Closures definido mediante la palabra reservada use es estático, mientras que los atributos tanto de los Closures como de las Lamdbas son públicos.

También se pueden pasar métodos por referencia para montar funciones recursivas.

<?php

$factorial = function( $n ) use ( &$factorial ) {
if(
$n == 1 ) return 1;
return
$factorial( $n - 1 ) * $n;
};
print
'Factorial='.$factorial( 8 );
?>



Es curioso el var_dump que nos devuelve, Php ya detecta que es una función recursiva.

object(Closure)#66 (2) {
  ["static"]=>
  array(1) {
    ["factorial"]=>
    *RECURSION*
  }
  ["parameter"]=>
  array(1) {
    ["$n"]=>
    string(10) ""
  }
}

Espero que haya sido interesante:

Oskar

pd: la biografía usada, algunos de los ejemplos de este texto son sacados de la biografía.
http://www.ibm.com/developerworks/library/os-php-5.3new2/
http://culttt.com/2013/03/25/what-are-php-lambdas-and-closures/
http://www.phpbuilder.com/articles/application-architecture/optimization/lambdas-in-php.html
http://docs.hhvm.com/manual/en/hack.lambda.php
http://stackoverflow.com/questions/1909002/what-use-is-lambda-in-php
http://fabien.potencier.org/on-php-5-3-lambda-functions-and-closures.html
http://php.net/manual/en/functions.anonymous.php
http://php.net/manual/es/class.closure.php