PHP y el sosiego lógico y pragmático

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”

Los comentarios están cerrados.

Sentimos molestarte con lo de las Cookies, pero es por imperativo legal. Puedes ver aquí la Política de Cookies, si continúas navegando te informo que la estás aceptando ;)    Ver
Privacidad