Cuando en PHP se hace necesario realizar comparaciones, es sabido que se dispone de dos tipos de condiciones:
igualdad, que se lleva a cabo mediante el operador == e
idéntico, que se lleva a cabo mediante el operador ===
De tal forma, dadas las variables $a = «1» y $b = 1, entonces $a == $b será True mientras que $a === $b, será False:
$ php -a
Interactive shell
php > $a = "1";
php > $b = 1;
php > print $a == $b;
1
php > print $a === $b;
php >
Lo anterior puede ser muy útil, si lo que se desea es comprobar si ambas variables poseen asignado el mismo valor, sin importar su tipo de datos. Esta, precisamente, es la diferencia entre los operadores == y ===.
PHP realiza la conversión de tipos al momento de efectuar la comparación. Y como vimos, puede ser útil. Pero, en pro de ser prácticos ¿es correcto sosegar el pragmatismo o peor aún, el sentido lógico?
Para PHP, 15 acreedores + 20 deudores es lo mismo que 35 acreedores:
php > $a = "15 acreedores";
php > $b = "20 deudores";
php > $c = "35 acreedores";
php > print $a + $b == $c;
1
php > print $a + $b != $c;
php >
Podríamos creer que con tan solo utilizar el operador ===, lo anterior se resolvería. Pero veamos que sucede si solo se convierte a entero la variable $c y se compara la identidad mediante el operador ===:
php > $a = "15 acreedores";
php > $b = "20 deudores";
php > $c = "35 acreedores";
php > print $a + $b === (int)$c;
1
Para PHP, la suma de dos variables de tipo string son idénticas no solo en cuanto a valor sino también, en cuanto a tipo de datos. Esto se puede ver aún mejor en el siguiente ejemplo:
php > $a = "15 acreedores";
php > $b = "20 deudores";
php > $c = 35;
php > print $a + $b === $c;
1
Según la lógica de PHP, lo anterior estaría justificado por el hecho de que al sumar aritméticamente dos variables que contienen un entero al inicio, éstas, son convertidas a entero previamente. Ergo, el resultado de la suma de dos enteros será idéntico al entero del mismo valor con el cuál se compara dicha identidad. Pero, no olvidar, que no solo para PHP serán idénticos. Lo mismo sucede, por ejemplo, en Perl, ya que son lenguajes que no mantienen una lógica pragmática, sino más bien, práctica.
Sin embargo, la lógica de PHP (como la de Perl) parece estar basada en un razonamiento lateral más semejante al de la medicina que al razonamiento lógico matemático. Pues es de público conocimiento, la frase «en medicina, 2 + 2 no siempre es 4». Como todo metáfora, se basa en un razonamiento lateral dado que se trata a enfermos y no a las enfermedades.
Pero esto, no sucede en otros lenguajes de programación. Veamos el mismo ejemplo en Python:
>>> a = "15 acreedores"
>>> b = "20 deudores"
>>> c = 35
>>> a + b == c
False
>>> a + b
'15 acreedores20 deudores'
(Nota: por favor, notar que en Python no existe el operador ===)
Pero profundicemos esto aún más:
php > print is_int($a + $b);
1
Para PHP, efectivamente la suma de dos variables de tipo string, arroja un resultado de tipo entero. Y esto, incluso aunque las variables de tipo string, no posean ningún valor numérico asociado:
php > $a = "foo";
php > $b = "bar";
php > print is_int($a + $b);
1
Esto es, porque como comenté anteriormente, al intentar sumar aritméticamente dos (o más) variables de tipo string, PHP, las convierte a entero:
php > settype($a, 'int');
php > print $a;
0
php > settype($b, 'int');
php > print $b;
0
Ahora, preguntémosle a Python que opina al respecto:
>>> isinstance(a + b, int)
False
Para Python, la suma de dos (o más) variables, no da como resultado una instancia del objeto int, simplemente porque Python, no realiza una conversión previa de los tipos. Por el contrario, mantiene una lógica pragmática.
Veamos ahora que sucede si se desea convertir una variable de tipo string a entero, en Python. Veamos diferentes casos:
>>> a = "15 acreedores"
>>> int(a)
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid literal for int() with base 10: '15 acreedores'
>>> a = "15"
>>> int(a)
15
>>> a = "foo"
>>> int(a)
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid literal for int() with base 10: 'foo'
Python, en los 3 casos, a buscado -lógicamente- el literal de un entero para efectuar la conversión solicitada. En el primer y tercer caso, arrojó un error, puesto que efectivamente, ninguna de las dos variables representaba el literal de un entero.
Así como Perl realiza la misma lógica de conversión que PHP, hasta lenguajes como JavaScript son aún más pragmáticos que PHP:
a = '15 acreedores';
b = '20 deudores';
a + b;
15 acreedores20 deudores
(Utilizando el Shell interactivo JavaScript de Mozilla: https://developer.mozilla.org/es/docs/Introducci%C3%B3n_al_shell_de_JavaScript)
Lo llamativo de todo esto, es que uno puedo esmerarse en justificar la lógica de PHP, pero sin embargo, las argumentaciones detractoras poseen aún más sustento que las justificativas. Un ejemplo más de ello, está en la argumentación lingüística de los términos empleados por el propio lenguaje en su documentación.
En la lengua hispana, el adjetivo igual tiene varias acepciones. Tres de ellas, según la Real Academia Española, son:
1. adj. De la misma naturaleza, cantidad o calidad de otra cosa.
3. adj. Muy parecido o semejante.
7. adj. De la misma clase o condición.
Este último, también utilizado como sustantivo.
En el caso del adjetivo idéntico, las acepciones son solo dos:
1. adj. Dicho de una cosa: Que es lo mismo que otra con que se compara.
2. adj. Muy parecido.
Pero aquí, quien también se utiliza como sustantivo, es la primera acepción.
Para el uso que PHP hace del término igual e idéntico, la acepción empleada es la misma en ambos casos:
Igual: aceptación 3. adj. Muy parecido o semejante.
Idéntico: acepción 2. adj. Muy parecido.
Pero esto, no termina aquí. Un criterio menos claro, se aplica a la comparación de variables nulas y vacías.
Pero veamos primero cómo define PHP el concepto NULL:
«El valor especial NULL representa una variable sin valor (…) Una variable es considerada null si:
se le ha asignado la constante NULL. no se le ha asignado un valor todavía. se ha destruido con unset()(…)»
Fuente: http://php.net/manual/en/language.types.null.php
Mientras tanto, define a empty (variable vacía) como:
«(…) Una variable se considera vacía si no existe [o] si su valor es igual a FALSE (…)» Fuente: http://www.php.net/manual/es/function.empty.php
Al aclarar «si su valor es igual a False», caemos nuevamente en la ambigüedad de igualdad versus identidad. Pero veamos como responde PHP en cada caso:
php > $a = NULL;
php > $b = "";
php > print $a == $b;
1
php > print $a === $b;
php > print empty($a);
1
php > print empty($b);
1
php > print is_null($a);
1
php > print is_null($b);
php > $c = 0;
php > $d = False;
php > $e = 0.0;
php > $f = array();
php > print $a == $c;
1
php > print $c == $b;
1
php > print empty($c);
1
php > print is_null($c);
php > print $c == $d;
1
php > print $c == $f;
php > print $c == $e;
1
php > print $e == $a;
1
php > print $e == $b;
1
php > print is_null($f);
php > print empty($f);
1
php > print empty($a);
1
php > print $a == $f;
1
php > print empty($b);
1
php > print $f == $b;
Cómo se puede observar, las respuestas de PHP parecen ser bastante ambiguas. Creo que la más llamativa y ambigua de todas, podría ser la comparativa entre $b y $f:
php > $a = NULL;
php > $b = "";
php > $f = array();
php > print empty($b);
1
php > print empty($f);
1
php > print $a == $b;
1
php > print $f == $b;
php > print $a == $f;
1
Un principio de lógica indica que:
si A es igual a B y A también es igual F, entonces F, es igual a B.
Sin embargo, para PHP, esto no es así. Para PHP, A es igual B y también es igual a F, pero paradójicamente, F no es igual a B. Recordemos, por favor, que para PHP el concepto de igualdad, no compara el tipo de datos. Sin embargo, en este último caso, PHP ha tenido en cuenta que si bien $b y $f tienen un valor vacío, $b es distinto que $f porque es un valor vacío de tipo string, mientras que el de $f, es de tipo array.
Como nota humorística se podría decir que PHP es como esos amigos poco honestos, que te dicen lo que quieres escuchar en vez de la verdad de lo que piensan. Personalmente, prefiero que mis amigos, sean honestos conmigo, aunque lo que tengan para decirme, no me agrade o no sea lo que esperaba escuchar xD
No obstante y más allá de toda broma, este artículo no pretende servir «de detractor» para PHP, sino para alertarte de lo que debes hacer en cada caso. Ten en cuenta siempre, qué es exactamente lo que deseas comparar o validar y consulta muy bien la documentación de PHP, antes de intentar «adivinar» o peor aún, utilizar la lógica, sobretodo, si vienes de otros lenguajes.
11 ideas sobre “PHP y el sosiego lógico y pragmático”
Esta bueno el articulo, aunque si te pones a ver mientras los scripts corran no hay porque rebuscar tanto ….
Te equivocás. Un script puede correr con fallos no esperados, que no necesariamente, escribirán errores en los logs.
Por eso, si te dedicas a la ingeniería de Software, es SUMAMENTE NECESARIO tener en cuenta que PHP no es un lenguaje pragmático. En cambio, aplica tu criterio, si lo que se desarrolla son páginas Web. Pero para la ingeniería, tu criterio pondría en riesgo el resultado de las operaciones.
Eugenia, yo creo que te estaban trolleando con el comentario anterior, saludos 😉
Hola Eugenia, un placer leerte, recientemente leí tu entrevista en el blog humanos (.cu) y me decidí a pasarme por acá.
Actualmente estoy usando Symfony 2 en el trabajo y sufro todas y cada unas de las inconsistencias de PHP, uff, que falta de concordancia cuando lo miras como un todo. Soy de la opinión (al igual que Jeff Attwood [1]) que no se deberían comenzar nuevos proyectos en PHP. Al menos no existiendo genialidades como django, rails, flask, sinatra, etc…
[1] http://www.codinghorror.com/blog/2012/06/the-php-singularity.html
xr09…. en PHP existen genialidades aún mejores (?) que Django, como EuropioEngine!!!!!!! Es lo máximo!! www.europio.org
Leyendo el código, se ve bien, me gusta lo directo que es, pero lo mio con PHP no tiene remedio, una vez [1] hasta traté de que se pareciera más a Python, pero eventualmente siempre tienes que bajarte del API y charlar un rato con el lenguaje en bruto. XD
[1] https://bitbucket.org/xr09/parsel/
PD: Me gustaría ver tu framework implementado en Python, quizás si encontraras la manera más rápida de convertir un programador PHP a Python pudiera encontrar un nicho que eplotar, el problema de los prog. PHP es que no quieren perder tiempo aprendiendo un leng. nuevo, y al final «pierden» mucho más.
xr09, tengo cinco cosas para decirte:
1. Europio
2. no
3. es
4. un
5. Framework
Me siento ofendida cual Maradona confundido con Pelé 😛
Jeje, lo capto es un «engine» o meta fram… ejem, un engine. 😉
Por eso me gustan los lenguajes fuertemente tipados. Excelente artículo!!!
Estimo que PHP entiende lo siguiente:
php > $a = NULL;
php > $b = «»;
php > $f = array();
$a es igual a $b porque ambos son NULL? o sea que la cadena «» es NULL? depende de la implementación de Strings, por ejemplo en Java «» no es NULL, es una cadena vacía.
$a es igual a $f porque un arreglo vacío apunta a NULL? depende de la estructura de los arreglos (su implementación con punteros), por ejemplo si tiene celda de cabecera, un arreglo inicializado jamás apuntaría a NULL, sino a su celda de cabecera.
Entonces por qué $b no es igual a $f? y por qué $a es igual a $f y a $b?
En un lenguaje fuertemente tipado te da error de compilación y chau jejeje.
Saludos!!!
MUY buen articulo men…. La verdad tengo años usando php y nunca me habia topado con esta informacion =S. Esta interesante y seguire buscando a ver, aunque no lo creas puede servir mas de ayuda de lo que crees.
Como siempre… ¡Maravillado!. Me enganché con la autora gracias a su manual de programación MVC en PHP. Para acotar que el manual completo de php puede descargarse en formato CHM, a mi me resulta muy útil consultarle incluso cuando codeo y no tengo conexión a la red de redes.
Saludos Eugenia! =)