¿Cómo uso variables booleanas en Perl?

220

Yo he tratado:

$var = false;
$var = FALSE;
$var = False;

Ninguno de estos trabajos. Me sale el mensaje de error

No se permiten palabras falsas "falsas" mientras se usan "subs estrictos".
Chad DeShon
fuente
37
Es posible que desee comenzar con mi libro Learning Perl . Es más fácil que adivinar qué hacer hasta que lo hagas bien (monos, máquinas de escribir y Hamlet, y todo eso). :)
brian d foy

Respuestas:

285

En Perl, lo siguiente se evalúa como falso en condicionales:

0
'0'
undef
''  # Empty scalar
()  # Empty list
('')

Lo demás es verdad. No hay palabras vacías para trueo false.

Alan Haggai Alavi
fuente
2
@BlueWaldo: también puede usar cmp y <=> al comparar y asignar los resultados de la comparación a un escalar. $ var = $ var1 cmp $ var2; 'cmp' y '<=>' (usado para comparaciones numéricas) devuelve -1, 0 o 1 si el argumento izquierdo es menor, igual o mayor que el argumento derecho. No es booleano, pero a veces es posible que desee saber si un argumento es igual o menor o mayor que el otro en lugar de simplemente igual o no igual.
user118435
99
Problema 1: una lista vacía no es falsa, ya que es imposible verificar si una lista es verdadera o falsa. Se devuelve una lista vacía en contexto escalar undef.
ikegami
44
Problema 2: ('')y ''son del mismo valor. Creo que quería implicar una lista con un elemento que consiste en una cadena vacía (aunque los padres no crean listas), pero como ya he mencionado, es imposible verificar si una lista es verdadera o falsa.
ikegami
66
Problema 3: Los objetos con un operador booleano sobrecargado también pueden ser falsos.
ikegami
15
@eternicode, Perl tiene dos valores específicos que usa cuando necesita devolver verdadero y falso, por lo que no solo tiene booleanos, tiene verdadero ( !0aka PL_sv_yes) y falso ( !1aka PL_sv_no). ¿O estás diciendo que Perl debería croar cada vez que se pruebe la veracidad de algo distinto a estos dos valores? Eso sería completamente horrible. por ejemplo, evitaría$x ||= $default;
ikegami
71

La definición más completa y concisa de falso que he encontrado es:

Todo lo que se convierte en cadena vacía o cadena 0es falso. Todo lo demás es verdad.

Por lo tanto, los siguientes valores son falsos:

  • La cadena vacía
  • Valor numérico cero
  • Un valor indefinido
  • Un objeto con un operador booleano sobrecargado que evalúa uno de los anteriores.
  • Una variable mágica que se evalúa como una de las anteriores en la búsqueda.

Tenga en cuenta que una lista vacía literal se evalúa como un valor indefinido en contexto escalar, por lo que se evalúa como algo falso.


Una nota sobre "ceros verdaderos"

Mientras que los números que se encadenan 0son falsos, las cadenas que se numeran a cero no son necesariamente. Las únicas cadenas falsas son 0y la cadena vacía. Cualquier otra cadena, incluso si se numera a cero, es verdadera.

Las siguientes son cadenas que son verdaderas como un booleano y cero como un número:

  • Sin peligro:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Con una advertencia:
    • Cualquier cadena para la cual Scalar::Util::looks_like_numberdevuelve falso. (por ejemplo "abc")
ikegami
fuente
si entendí bien la palabra verdadero en Mientras que los números que se convierten en cadena a 0 son verdaderos, deben ser falsos o (para evitar confusiones) evaluar a falsos .
Dmitry Korolyov
1
Su definición "concisa" es inconsistente con su explicación más larga. Considere lo siguiente: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Ahora $valuese stringificará a "XXX" pero se boolifica a falso.
tobyink
1
@tobyink, la versión concisa no es perfecta, simplemente la mejor que he encontrado. Está destinado a ser práctico, no lo abarca todo. Tenga en cuenta que el valor devuelto por su boolhace stringify a 0. Además, no se recomienda crear sobrecargas inconsistentes, y los valores que devuelve podrían considerarse tales. (por ejemplo, una &&puede ser optimizada en una ||, así que si éstos fueran incompatibles, tendría un problema.)
Ikegami
No estoy seguro si 0x00está cubierto aquí.
Zaid
@Zaid, ¿Te refieres al valor devuelto por el código 0x00(el valor numérico cero) o la cadena 0x00(para la cual looks_like_numberes falso)? De cualquier manera, ya está cubierto.
ikegami
59

Perl no tiene un tipo booleano nativo, pero puede usar la comparación de enteros o cadenas para obtener el mismo comportamiento. El ejemplo de Alan es una buena manera de hacerlo usando la comparación de enteros. Aquí hay un ejemplo

my $boolean = 0;
if ( $boolean ) {
    print "$boolean evaluates to true\n";
} else {
    print "$boolean evaluates to false\n";
}

Una cosa que he hecho en algunos de mis programas es agregar el mismo comportamiento usando una constante:

#!/usr/bin/perl

use strict;
use warnings;

use constant false => 0;
use constant true  => 1;

my $val1 = true;
my $val2 = false;

print $val1, " && ", $val2;
if ( $val1 && $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

print $val1, " || ", $val2;
if ( $val1 || $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

Las líneas marcadas en "usar constante" definen una constante llamada true que siempre se evalúa en 1, y una constante llamada false que siempre se evalúa en 0. Debido a la forma en que las constantes se definen en Perl, las siguientes líneas de código también fallan:

true = 0;
true = false;

El mensaje de error debería decir algo como "No se puede modificar la constante en la asignación escalar".

Vi eso en uno de los comentarios que preguntaste sobre la comparación de cadenas. Debe saber que debido a que Perl combina cadenas y tipos numéricos en variables escalares, tiene una sintaxis diferente para comparar cadenas y números:

my $var1 = "5.0";
my $var2 = "5";

print "using operator eq\n";
if ( $var1 eq $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

print "using operator ==\n";
if ( $var1 == $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

La diferencia entre estos operadores es una fuente muy común de confusión en Perl.

James Thompson
fuente
55
use warnings;en lugar de#! perl -w
Brad Gilbert
11
Usar las constantes como macros de un hombre pobre de esa manera es peligroso. Estos ejemplos de código no son equivalentes: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, que podría no ser obvio para un observador casual. (Y sí, el último ejemplo es un estilo de programación pobre, pero eso no viene al caso).
Zano el
16

Recomiendo use boolean;. Sin embargo, debe instalar el módulo booleano desde cpan.

xenoterracida
fuente
77
En Perl, como en la vida, hay muchas verdades. A los inexpertos les gusta escribir cosas tontas como if ($my_true_value == true). Pretender que existe una Verdadera Verdad es, en mi experiencia, un camino hacia el dolor y un código ineficiente.
tjd
2
Perl es filosófico por naturaleza
ILMostro_7
13

Mis favoritos siempre han sido

use constant FALSE => 1==0;
use constant TRUE => not FALSE;

que es completamente independiente de la representación interna.

syck
fuente
55
Brillante. ¡Usted solo arregló el lenguaje de programación Perl!
Nostalg.io
8

Encontré un tutorial que tiene una buena explicación sobre qué valores son verdaderos y falsos en Perl . Establece que:

Los siguientes valores escalares se consideran falsos:

  • undef - el valor indefinido
  • 0 el número 0, incluso si lo escribe como 000 o 0.0
  • '' La cuerda vacía.
  • '0' la cadena que contiene un solo dígito 0.

Todos los demás valores escalares, incluidos los siguientes, son verdaderos:

  • 1 cualquier número que no sea 0
  • ' ' la cuerda con un espacio en ella
  • '00' dos o más 0 caracteres en una cadena
  • "0\n" un 0 seguido de una nueva línea
  • 'true'
  • 'false' Sí, incluso la cadena 'falso' se evalúa como verdadero.

Hay otro buen tutorial que explica acerca de Perl verdadero y falso .

serenesat
fuente
6

Hermosa explicación dada por bobf para los valores booleanos: ¿ Verdadero o falso? Una guía de referencia rápida

Pruebas de verdad para diferentes valores.

                       Result of the expression when $var is:

Expression          | 1      | '0.0'  | a string | 0     | empty str | undef
--------------------+--------+--------+----------+-------+-----------+-------
if( $var )          | true   | true   | true     | false | false     | false
if( defined $var )  | true   | true   | true     | true  | true      | false
if( $var eq '' )    | false  | false  | false    | false | true      | true
if( $var == 0 )     | false  | true   | true     | true  | true      | true
Bharat
fuente
Mala respuesta, pero una fuente fuerte y de buena reputación en perlmonks.org. Sería bueno tener contenido real en lugar de un comentario y un enlace. : - /
ILMostro_7
0

use el siguiente prefijo de archivo, esto agregará a su script perl eTRUE y eFALSE, en realidad será REAL (!) verdadero y falso (al igual que java)

#!/usr/bin/perl
use strict;
use warnings;

use constant { #real true false, compatible with encode_json decode_json for later (we don't want field:false... will be field:0...)
                eTRUE  =>  bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                eFALSE =>  bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
             };

En realidad, hay algunas razones por las que deberías usar eso.

Mi razón es que al trabajar con JSON, tengo 0 y 1 como valores para las claves, pero este truco se asegurará de que se mantengan los valores correctos a lo largo de su secuencia de comandos.


fuente