PHP es KK. Un ejemplo práctico
Hoy mi amigo Ernesto Alvarez me mostró un pequeñísimo ejemplo de porqué PHP es una mierda. La semántica del lenguaje deja muuuucho que desear.
El programa:
<?php
echo count == 0;# . "\n";
?>
Muestra "1" en la salida por standard output.
En cambio si dejamos el enter comentado no muestra nada. Este es el código que no muestra nada:
<?php
echo count == 0 . "\n";
?>
Bueno, una cosa más para hacer leña del árbol caído.
Hasta la próxima, amigos.
Update: Escribí una segunda parte de esto en mi artículo Si php es KK, ¿por qué lo usan tanto?.
28 comentarios:
Demostraste que el . tiene mayor precedencia que la comparación... o sea... Wow!?
No, muestro como elecciones feas de precedencias hacen que el código no haga lo que quiero que haga. PHP es feo porque tiene "sorpresitas" todo el tiempo (entre otras cosas).
Aparte, ¿por qué %$^&**@# tiene que count == 0 ser verdadero? También a esas cosas me refiero cuando digo que PHP es KK.
+ también tiene mayor precedencia que ==; en este caso es algo poco sorprendente :/...
Ahora sí estoy de acuerdo en que: ¿Por qué no imprime nada?
Aparte, count es una constante mientras que $count es una variable; ojo ahí (aunque en este caso hace lo mismo).
(Y lo mismo que si yo pongo echo count; no imprime nada, pero me dice "Notice: Use of undefined constant count - assumed 'count' in /home/tordek/- on line 2"; o sea "se asume que el valor de count es 'count', pero no imprimo nada?)
Ah, y, lo que vos querés hacer para imprimir el \n después de la comparación, cuando usas echo, es poner echo $count == 0, "\n";
No defiendo a PHP, sólo digo que hay cosas estúpidas y cosas que no te gustan. Esta es una cosa que no te gusta (que el punto tenga mayor precedencia). (Cosa estúpida es que algunas funciones de string se llamen str_loquesea, y otras strloquesea, y las de array, array_loquesea.)
De todas maneras, ¿"count" == 0 es verdadero? ¿o es que se lo confunde con la función count de php? En cualquiera de los 2 casos, ¿tiene algún sentido?
count == 0 es verdadero.
0 == "0" es verdadero.
count == "0" es falso.
O sea, == no es transitivo!!!?!!!
Hay una tabla que dice las igualdades; en particular, count al ser indefinido tiene valor Null; Null == 0 es verdadero, 0 = "0" es verdadeto, Null = "0" es falso.
Esta sí es un poco que decisión estúpida... pero también es un poco de "¿por qué carajo usas un valor que no definiste?".
Me vas a decir que si en C yo pongo
int main(){
int a;
printf("%d",a);
}
y me imprime cualquier cosa es porque C es una mierda... el funcionamiento está documentado: Cuando inicializás una variable sin asignarle el valor, tiene el valor que la posición de memoria que corresponde tenía antes. (Hay compiladores que lo setean a 0 por defecto, pero según el estándar eso es innecesario, y tu código (y no el compilador) está mal por intentar confiarse en eso.)
En realidad lo que digo es que rompe las espectativas que yo (y creo que mucha otra gente) tengo sobre la semántica del lenguaje. Esa superposición de roturas de expectativas es lo que lo hace una mierda (en mi opinión). En ningún momento dije estuviera mal documentado. De hecho la documentación de php es FABULOSA. Lo que digo es que las elecciones semánticas en el lenguaje son una bosta.
PHP es una KK... y qué lenguaje no lo es?? Todos, PERO TODOS los lenguajes tienen sus cosillas, algunas más graves que otras. En fin, de todas formas no programo en PHP salvo alguna pavada cada tanto.
Los lenguajes (como los programas) son escritos por personas, ergo, no hay lenguaje perfecto. Unicamente algunos son mejores que otros para ciertas tareas, y según la experiencia de cada uno.
eh, loco
Por lo visto al menda este los suspendieron en programación.
Buenas...
Hacer algo como esto:
echo count == 0 . "\n";
No es muy coherente q digamos... No hay q hechar la culpa al lenguaje si uno hace cualquier cosa...
Saludos!
¿Por qué no?
Un lenguaje sensato no haría que cualquier función sea igual a 0 y si realmente no tiene sentido comparar count y 0 debería dar un error (algo así como lanzar una excepción). Aunque ahora que lo pienso mejor count == 0 debería ser FALSO. Ese es el ejemplo práctico de KKcidad del que habla lo que escribí arriba de todo.
Veamos...
PHP es un lenguaje dinámico.
count no está inicializada -> count se crea.
Estas comparándolo con un entero. La lógica dicta que count es un entero.
Si creo una variable y no le asigno un valor, hay dos opciones:
a) Null (no es un número, comparación inválida, error [o, como hace SQL, null comparado con cualquier cosa = null])
b) 0. 0 == 0. Si me decís que es falso, te revoco tu licencia de programador.
Y ahora me doy cuenta tras releer 20 veces tu post hasta que le encontré sentido...
count no es "la funcion count"; count es "la constante count".
El primer parámetro de array_map es una función. Se lo pasa como string. Esto quiere decir que si vos tenés
array_map(count,$array);
hiciste cagada. La forma correcta es
array_map("count",$array);
Saludos, y espero que ahora te cierre.
¿Y eso que acabás de escribir te parece algo que harías en un lenguaje de programación que inventes vos?
Todas esas reglas a las que hacés referencia en el análisis de tu último post son las que hacen que php sea KK.
En particular, tomo una que me parece hasta chistosa:
Si creo una variable y no le asigno un valor, hay dos opciones:
a) Null [comentario sacado]
b) 0. 0
Ahora, ¿por qué no puede ser?:
c) ""
d) 0.0 (floating point)
e) 5
f) "esta variable no está inicializada" (o en inglés)
g) array( 1,2,3,4,5 )
Porque para mi son tan malas como la opción b).
Y una cosa más. En php count no es una variable, $count lo es (y son cosas distintas). En php count tiene el valor del string "count" siempre. Al menos es lo que acabo de probar en el intérprete de php de mi PC:
$ php
<?
echo count
?>
^D
SALIDA:count
Pero puede ser que php se comporte distinto cuando comparás un string con el 0. En todo caso sería otra corroboración más para la teoría que postulo en el post.
Aureliano.
PD: Me encanta que estemos teniendo esta discusión, creo que nos aporta a todos (a mi seguro)
No entendí lo del array_map. ¿Podés explicarlo un poco más?
Array_map es una función que aplica una función a un array (la "mapea"); ejemplo:
function sumar1(x) {
return x + 1;
}
print_r(array_map("sumar1",[1,2,3,4,5]));
[2,3,4,5,6]
Disclaimer: lo ejecuto de memoria.
Tenés razón, count no es una variable; es una constante.
De http://ar2.php.net/manual/es/language.constants.php:
Si usas una constante todavia no definida, PHP asume que estás refiriéndote al nombre de la constante en si.
Por lo tanto:
count = "count";
Entonces lo tuyo se transforma en:
0 == "count";
Esto, poco lógico, da verdadero. ¿Por qué? Bien... empecemos por el hecho de comparar un string con un entero...
Php al ver esa comparación parsea el string, pero como no tiene números devuelve 0. (Acá estoy de acuerdo en que debería dar un error, en vez de devolver 0).
En el otro caso, hacés 0 . "\n" => tranformas el 0 en un string. Comparás "count" con "0\n".
Ahora, en este segundo caso, es total y absolutamente obvio que son strings diferentes. Resultado: falso. (Nuevamente, sí, debería imprimir un 0, o un "falso", o lo que sea... pero vos tampoco deberías imprimir el resultado de una comparación; sólo usarlo en algo que consuma un booleano.)
Es mitad-y-mitad.
(Si se cuelga un poco es pq mi ups me está chillando; se me cortó la luz, y en seguida se muere mi compu.)
Como escapeo el codigo php que no me deja poner???
Bueno, no voy a decir que s KK ni PRO ni ruralista, simplemente voy a poner los puntos sobre las "ies" y hasta los nyuflos sobre las enyes (sobre todo ahora que podremos tenes dominios con nuestras hermosas ñ).
En primer lugar, si estas desarrollando en PHP, deberías sacar el modo que yo le llamo "mudo" y hacer que se muestren todos los WARNING, ERROR y NOTICE.
Como?
a) en .htaccess con "php_value error_reporting 6143"
b) en el propio php con "error_reporting(E_ALL);"
Ahora, un poco de teoría:
Operadores de Comparación en PHP:
http://ar2.php.net/manual/es/language.operators.comparison.php
Probemos
<?
echo "a1: " . (false==0) . "<br />";
echo "a2: " . (false===0) . "<br />";
echo "b1: " . (null==0) . "<br />";
echo "b2: " . (null===0) . "<br />";
echo "c1: " . (null==false) . "<br />";
echo "c2: " . (null===false) . "<br />";
?>
Salida:
a1: 1
a2:
b1: 1
b2:
c1: 1
c2:
Conclusión:
a)
false y null son 0 (en c sería 0 o '\0' o '0x00')
b)
Sin embargo, si hacemos una comparación estricta, PHP se da cuenta que no son lo mismo.
Un ejemplo de el error que se puede cometer con esta comparación, se encuentra en la ayuda de strpos:
http://ar2.php.net/manual/es/function.strpos.php
---
Hasta acá, no encuentro error alguno, es mas PHP va mas allá que otros lenguajes, incluso que lenguajes
"no scripting". C sabe diferenciar eso? que yo sepa no. Java? No se java. Visual Basic? Dije lenguajes!!... etc
Volviendo al ejemplo inicial:
<?
echo count == 0;# . "\n";
?>
Salida
Notice: Use of undefined constant count - assumed 'count' in [el script] on line 2
1
Conclusión: Avisa que es indefinida, avisa que asume que es 'count', compara y da true.
Esto está mal? podría pensarse que si, no obstante, el link que puse haciendo referencia a los
operadores de comparación dice:
"Si compara un entero con una cadena, la cadena es convertida a un número. Si compara dos cadenas
numéricas, ellas son comparadas como enteros. Estas reglas también se aplican a la sentencia switch."
Si verificamos con intval("count"), comprobamos que es 0.
Entonces, la comparación sería 0 = 0 = NO HAY ERROR.
Sigamos:
<?
echo count === 0;# . "\n";
?>
Salida:
Notice: Use of undefined constant count - assumed 'count' in [el script] on line 2
Conclusión: la comparación estricta, nos vuelve a decir la verdad y no se equivoca.
Por último:
<?
echo count == 0 . "\n";
?>
Salida:
Notice: Use of undefined constant count - assumed 'count' in [el script] on line 2
Conclusión: El mansaje debería haber sido:
ERROR: Idiota. Que quiere comparar???
Escriba: echo (count == 0) . "\n"; y valla a hacer un curso al IAC
O como dijo Tordek, "Demostraste que el . tiene mayor precedencia que la comparación... o sea... Wow!?"
----
Conclusión general: alguien podría decir que el comportamiento es raro, al menos no es un comportamiento
que yo viera antes en otro lenguaje, pero está 100% documentado, por lo tanto no es erróneo.
Conclusión personal: Aurelio, decile a Ernestito que busque otra cosa para fundamentar (estoy 100% seguro que
la va a encontrar).
PD: existe el IAC todavía?
PD2: tuve que usar esto: http://www.simplebits.com/cgi-bin/simplecode.pl?mode=process
para que me dejara postear php, porque no me dejaba.
Gracias, locutus, por prácticamente copiar palabra por palabra mi post: http://blog.tordek.com.ar/2008/05/en-defensa-de-php/
Hubieras puesto el link y me ahorraba escribir :P
Saludos
Leo (AKA: Locotus). En el post no me quejo que esté mal documentado php. Me quejo que la forma en la que anda es una mierda. Que tiene cosas increíblemente anti-intuitivas (como una igualdad no transitiva). Y, a lo largo de los comentarios pude aprender algunas cosas que no sabía de php (y otras que me había olvidado) pero sigo manteniendo que php (como lenguaje) es un adefecio. Nada más, nada menos.
Aún así, lo usaron para hacer cosas re-grosas, y a eso me refiero en el post que hace follow up (mirá el post).
Gracias Tordek y Locutos por sus aportaciones.
Para mejores argumentos sobre porqué PHP es una mierda, miren http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/
La ignorancia hace mucho daño.
Cada vez que veo alguien echando pestes sobre algo hay alguien que sabe más de esa materia y que puede refutar hasta la última palabra.
Aprende a usar algo MUY bien y podrás hacer algo más que mierda.
Léete los manuales (RTFM) y verás con conocimiento, o al menos con algo más de luz.
De un artesano aprendí, que no importa la herramienta, sino el arte con el cuál se usa. Con herramientas con las que tú comes, el hacía figuras de cerámica MUY buenas.
Muy interesante el debate... ciertamente se aprende :)
Saludos.
Publicar un comentario