Diversión con conversiones de tipo automáticas
Los que me conocen saben que PHP no es santo de mi devoción. Sin embargo, es un lenguaje con el que tengo que lidiar a menudo y, por qué no decirlo, me permite comer todos los días (una costumbre que adquirí hace ya muchos años :P).
La cuestión es que hoy tropecé con una de esas cosas que, no por sabida, deja de tocarme las narices. Hay que reconocer, de todos modos, que no es algo exclusivo de PHP.
Resumiendo mucho, en PHP la siguiente comparación es cierta:
'rock' == 0
La explicación "lógica" es que el intérprete de PHP es un cachondo y realiza conversiones automáticas de tipo así que, si intentamos comparar una cadena y un entero, pues convertirá la cadena en un entero y realizará la comparación.
A esto hay que añadir que la conversión de la cadena 'rock' a entero es 0 (sí, tampoco es exclusivo de PHP). Así que, al final, pasamos a tener algo como 0 == 0.
Claro, el resultado de combinar estos dos comportamientos son escenarios tan surrealistas como este:
$genres = array('rock', 'blues', 0, 'jazz');
print in_array('rock', $genres); // cierto
print in_array('heavy', $genres); // ¡también cierto!
Lo que no deja de maravillarme es cómo los informáticos aceptamos esta clase de cosas como si fueran "lógicas".
Afortunadamente, otros lenguajes gestionan mucho mejor este tipo de situaciones. Como ejemplos, tomemos Ruby y Python. Tanto en uno como en otro, la comparación 'rock' == 0 devuelven falso. Incluso la comparación 1 == '1' también resulta falsa: una cosa es un entero y otra una cadena (aunque a nosotros puedan parecernos lo mismo en este caso).
En cuanto a la conversión de cadenas a números, he de reconocer que prefiero el modo en que lo hace Python, quien al intentar convertir una cadena como 'rock' a número, lanza una excepción.
En Ruby:
'rock'.to_i == 0 # cierto
Mientras que en Python:
>>> 0 == int('rock')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid literal for int() with base 10: 'rock'
En fin, antes de que alguien se enfade, supongo que es justo decir que es una cuestión de gustos. Pero yo tenía que desahogarme :-)
PD: si no me falla la memoria, que es posible, la etiqueta 'berrinche' la copié miserablemente del antiguo blog (ya cerrado) de Esteban Manchado.
Comments
Pues sí, tienes razón. Como es habitual, se me fue la bola ;)
Corregido. Muchas comprar cytotec gracias por avisar.
La verdad es que este tipo de cosas son las que nos vuelven locos a la hora de desarrollar. De ahí la importancia de conocer bien las reglas del juego de cada lenguaje. En PHP decidieron hacer uso del cast implícito con todas sus consecuencias. En cuanto a la función in_array podemos enviar el cast con un tercer parámetro en el caso de desear evitar este comportamiento.
Sí, lo del parámetro "strict" aparece en varias funciones además de in_array. De hecho, existe un operador "===" para ese tipo de comparaciones.
Lo que pasa es que, y por eso digo que es cuestión de gustos, me parece bastante poco "intuitivo". Y, personalmente, me parece molesto tener que preocuparme de esos detalles cuando estoy escribiendo código.
Saludos.
Jaja, sí, antes utilizaba «berrinches» :-D Qué tiempos aquéllos...
Por cierto, en uno de los ejemplos pusiste:
'rock'.to_s == 0 # cierto
Pero creo que quieres decir:
'rock'.to_i == 0 # cierto
Pues sí, tienes razón. Como es habitual, se me fue la bola ;)
Corregido. Muchas gracias por avisar.
Post new comment