En defensa de PHP
Mayo 19th, 2008Hace tiempo, Aurelianito puso en su blog un post acerca de un problema de PHP en particular, que
discutimos extensamente en sus comentarios.
El caso particular era:
< ? echo count == 0; ?> // imprime 1, mientras < ? echo count == 0."\n"; ?> // no imprime nada.
Hay muchas cosas mal en este ejemplo (medio sacado por los pelos), y no son todas culpa del lenguaje:
- count es una constante indefinida. Su valor es el string “count”;
- El primer ejemplo es una comparación string-entero.
- El segundo ejemplo es una comparación string-string.
El primer punto es una elección del lenguaje: prefiere devolver un string y tirar un warning, que morir. O sea, lo anterior es igual a:
< ? echo "count" == 0; ?> // imprime 1, mientras < ? echo "count" == 0."\n"; ?> // no imprime nada.
El tercero es lo más lógico: . tiene mayor precedencia que ==, y dado que PHP es de tipos débiles y dinámicos, estoy comparando "const" con "0\n", que obviamente son diferentes. Aunque no imprime nada.
PHP tiene muchos valores para falso: 0, false, null, entre otros. Una expresión falsa devuelve null. < ? echo null; ?> no imprime nada. QED.
Hasta ahora, estamos bien.
Ahora viene la parte rara: "count" == 0 devuelve 1.
Esta es una comparación entre un string y un entero… que, empezando por ahí, no tiene sentido…
pero aún así me devuelve un valor (y uno inesperado, por decir poco).
Pero la comparación, como dije, no tiene sentido, entonces PHP intenta convertir ambos valores a un
tipo que pueda comparar. Lo que PHP decidió es, en vez de transformar el número a un string,
transforma el string a un número. Obviamente que las letras no son números1, así que el parser analiza el string hasta el primer caracter que no forme un número2 y devuelve el número que haya encontrado hasta ahora.
Por ejemplo:
< ? assert("42" == 42); assert("42a" == 42); assert("4a2" == 4); assert("a42" == 0); //Y lo que nos importa: assert("a" == 0); ?>
Y ahí tenemos por qué nuestro "count" == 0 devuelve 1.
Estoy completamente de acuerdo en que la respuesta tiene poco sentido, pero no es culpa del lenguaje
que el programador compare dos tipos de datos que no tienen que ver uno con el otro.
Ah, y para los que prefieren que “42″ no sea igual a 42, pueden usar ===, una comparación mucho más estricta, que también revisa el tipo de ambos valores.
