Novedades para PHP 5.3: namespaces, closures, Phar
Enviado por clbustos el Jue, 31/07/2008 - 03:54.
Clasificado en:
Traduzco literal de php.net:
La próxima versión de PHP 5.3 introduce algunas nuevas características mayores como namespaces, closures, bindings tardío estático, funciones de i18n, secciones en los archivos INI, y Phar entre otras
¿Qué tiene de importante esto? Varias cosas:
- Namespaces: Una de las peticiones más frecuentes para PHP 5 era la presencia de los namespaces. Una vez desechada para las primeras versiones de PHP5, creí que no lo vería hasta PHP 6, pero me equivoqué. La gran ventaja de los namespaces es que evita la colisión de nombres de clases al incorporar bibliotecas de proyectos distintos.
- closures: algo que siempre he extrañado en PHP, al trabajar en Ruby o Javascript, es el uso de las closures. Para aquellos que no las conozcan, un closure en una función en las cuales una o más variables dependen del contexto dentro del cual se llaman. Para los que trabajan con javascript, su uso más común es otorgar la funcionalidad para un callback. Por ejemplo, en jQuery es común la estructura:
$(".mis_objetos_clickeables").click(function() {alert(this)});Si se dan cuenta, el parámetro para la función "click" es la definión de una función, en la cual 'this' corresponde al objeto que fue clickeado. 'this' sería entonces la variable dependiente del contexto y se define al momento de hacer click en uno de los objetos - Phar: No sé si es bueno o malo esto para la comunidad PHPera, pero es el intento de utilizar algo similar a los JAR de Java, lo que permite encapsular una biblioteca o aplicación completa en un solo archivo.
¿Ven? Son grandes noticias. Lo que más me pone contento son las closures, ya que ahorran una gran cantidad de código y facilitaran mucho el trabajo con aquellas funciones que requieren callbacks, como usort. Por lo visto, quedara algo así como :
- $a = array(3, 2, 5, 6, 1);
- usort($a, function ($a,$b) {$a==$b ? 0:(($a<$b)?-1:1);});
Lo cual es mucho más sintético que:
- function cmp($a, $b)
- {
- if ($a == $b) {
- return 0;
- }
- return ($a < $b) ? -1 : 1;
- }
- $a = array(3, 2, 5, 6, 1);
- usort($a, "cmp");
- 568 lecturas

Estimado, por los demás puntos, formidable, por el punto de los "closures", más teniendo en cuenta tu ejemplo, lo veo negativo. Seguimos pensando en "lenguajes / codificación" y no en lenguaje como apoyo para hacer sistemas" (que sí benefician para esto los namespaces y Phar, por ejemplo).
Creo que son herramientas que van a ayudar que el código sea "inentendible" (como el ejemplo).
Entiendo tal vez un caso como trabajar las interfaces, javascripts, etc, pero no lo veo nada práctico ni recomendable para la calidad de un sistema. No olvidar que pasamos el 80% del tiempo manteniendo, si tu me haces el código primero, yo vendré detrás tuyo, haré refactoring y lo dejaré como la segunda opción.
"Menos" no es "más", es "menos".
PD: los enlaces de la nota están en su mayoría rotos.
Estimado Enrique:
Muchas gracias por avisarme por los links rotos. En la emoción, al copiar textual el texto del sitio de php, se me olvidó que los URL estaban con dirección relativa.
Con respecto a los closures, creo que no elegí el mejor ejemplo. Te encuentro toda la razón con respecto a que hacer código más sintético puede ir en perjuicio de la claridad. Incluso, en el ejemplo que di, si reemplamos los operadores ternarios por secuencias if y separamos la definición de la función en una variable, evitamos separar la lógica del ordenamiento en una función aparte, lo cual es bastante incómodo por mi experiencia.
El problema de tu ejemplo de closures, es que NO es una closure. Tan sólo es una función anónima. Y son dos cosas bastante distintas.
Si realmente quieres ver la utilidad de las closures, necesitas ejemplos mejores... Y entender dónde está la diferencia con una simple función anónima. Intentaré explicarlo:
Closure es un objeto, una construcción que se produce en tiempo de ejecución y que abarca, tanto una función como su contexto de definición. Este contexto se cierra, es decir, ya no está accesible al resto del programa, pero sigue manteniéndose vivo porque existen referencias desde la función al contexto.
Lo que quiere decir ese párrafo no es más que lo siguiente. Tengamos un ejemplo como este (nota: quizá no es un ejemplo demasiado útil para la vida diaria, pero es un ejemplo clásico para hacer sencilla la explicación. Ah, y perdón si la sintaxis no es correcta; no he podido ver todos los detalles de la nueva sintaxis para closures):
<?php
function cicloColores($maximo) {
$i = 0;
$max = $maximo;
$colores = array('#fff', '#eee', '#ddd', '#ccc', '#bbb', '#aaa', '#999', '#888', '#777', '#666', '#555', '#444', '#333', '#222', '#111', '#000');
$siguiente = function () use (&$i, $max, $colores) {
$color = $colores[$i];
$i = ($i + 1) % $max;
return $color;
};
return $siguiente;
}
$generaColores = cicloColores(6);
?>
La llamada a cicloColores(6) devuelve una función. Pero una función que tiene asociado un estado. Si luego haces sucesivas llamadas a generaColores, te irá devolviendo cada vez el siguiente color. Ninguna de las variables usadas (el índice i, el máximo, el array de colores) es accesible desde otras partes de la aplicación. El contexto en que se definió la función ya está cerrado. Sin embargo, esas variables (ese contexto) no han desaparecido. Sigue vivo y referenciado desde la función.
Hacer que PHP soporte closures, quiere decir no sólo que se añade una sintaxis permitida, sino que el intérprete es capaz de mantener vivo ese contexto y hacer que esas referencias sigan siendo válidas cuando llamemos a generaColores() repetidamente.
Entiendo la negativa de algunos, quizá por miedo, quizá por desconocimiento, tanto a las closures como a las funciones anónimas. Sin embargo, lo entiendo sólo si nos quedamos en que PHP tiene ese ámbito de 'lenguaje para cualquiera', eso de que cualquiera escupe 20 líneas de PHP y lo chapurrea como sea y hace sus chapucillas. Pero realmente son conceptos muy potentes que hacen del lenguaje una herramienta capaz de resolver problemas más complejos de forma más sencilla. En el fondo closures y objetos son lo mismo.
Aunque también entiendo que se quiera preservar cierta simplicidad en el lenguaje y no se quiera implementar Lisp en PHP (que se acabará haciendo, claro, como se hace siempre).
Ah, y en el ejemplo de jQuery, tampoco es realmente una closure. Al ser this una palabra reservada que siempre hace referencia al objeto "dueño" del método donde se ejecuta, no hay realmente ninguna referencia especial al contexto de definición.
De hecho, de algún modo es el comportamiento opuesto. Según le asocies esa función al evento de un objeto o a otro, this resolverá a ese objeto en tiempo de ejecución, no al dueño de la función en tiempo de definición.
Enviar un comentario nuevo