Comment utiliser les variables booléennes en Perl?

220

J'ai essayé:

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

Aucun de ces travaux. Je reçois le message d'erreur

Les mots nus "false" ne sont pas autorisés lorsque "strict subs" est utilisé.
Chad DeShon
la source
37
Vous voudrez peut-être commencer par mon livre Learning Perl . C'est plus facile que de deviner quoi faire jusqu'à ce que vous ayez bien compris (singes, machines à écrire et Hamlet, et tout ça). :)
brian d foy

Réponses:

285

En Perl, ce qui suit est évalué à faux dans les conditions:

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

Le reste est vrai. Il n'y a pas de mots nus pour trueou false.

Alan Haggai Alavi
la source
2
@BlueWaldo: vous pouvez également utiliser cmp et <=> lors de la comparaison et de l'attribution des résultats de la comparaison à un scalaire. $ var = $ var1 cmp $ var2; 'cmp' et '<=>' (utilisés pour les comparaisons numériques) renvoient -1, 0 ou 1 si l'argument gauche est inférieur, égal ou supérieur à l'argument droit. Ce n'est pas booléen mais parfois vous voudrez peut-être savoir si un argument est égal ou inférieur ou supérieur à l'autre au lieu d'être juste égal ou non égal.
user118435
9
Problème 1: Une liste vide n'est pas fausse, car il est impossible de vérifier si une liste est vraie ou fausse. Une liste vide dans un contexte scalaire revient undef.
ikegami
4
Problème 2: ('')et ''ont la même valeur. Je pense que vous vouliez impliquer une liste avec un élément qui se compose d'une chaîne vide (même si les parens ne créent pas de listes), mais comme je l'ai déjà mentionné, il est impossible de vérifier si une liste est vraie ou fausse.
ikegami
6
Problème 3: Les objets avec un opérateur booléen surchargé peuvent également être faux.
ikegami
15
@eternicode, Perl a deux valeurs spécifiques qu'il utilise lorsqu'il doit renvoyer true et false, donc non seulement il a des booléens, il a true ( !0aka PL_sv_yes) et false ( !1aka PL_sv_no). Ou êtes-vous en train de dire que Perl devrait coasser chaque fois que quelque chose d'autre que ces deux valeurs est testé pour la vérité? Ce serait complètement affreux. Par exemple, cela empêcherait$x ||= $default;
ikegami
71

La définition la plus complète et concise de faux que j'ai rencontrée est:

Tout ce qui se transforme en chaîne vide ou en chaîne 0est faux. Tout le reste est vrai.

Par conséquent, les valeurs suivantes sont fausses:

  • La chaîne vide
  • Valeur numérique zéro
  • Une valeur indéfinie
  • Un objet avec un opérateur booléen surchargé qui évalue l'un des éléments ci-dessus.
  • Une variable magique qui s'évalue à l'une des précédentes lors de la récupération.

Gardez à l'esprit qu'un littéral de liste vide est évalué à une valeur indéfinie dans un contexte scalaire, il est donc évalué à quelque chose de faux.


Une note sur les "vrais zéros"

Alors que les nombres qui se stratifient en 0sont faux, les chaînes qui se chiffrent en zéro ne le sont pas nécessairement. Les seules fausses chaînes sont0 la chaîne vide. Toute autre chaîne, même si elle est de zéro, est vraie.

Les chaînes suivantes sont vraies en tant que booléen et zéro en tant que nombre:

  • Sans avertissement:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Avec un avertissement:
    • Toute chaîne pour laquelle Scalar::Util::looks_like_numberrenvoie false. (par exemple "abc")
ikegami
la source
si je vous ai bien compris, le mot vrai dans Bien que les nombres qui se transforment en 0 sont vrais devrait être faux ou (pour éviter toute confusion) évaluer faux .
Dmitry Korolyov
1
Votre définition "concise" ne correspond pas à votre explication plus longue. Considérez: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Maintenant, $valuese transforme en "XXX" mais booléen en faux.
tobyink
1
@tobyink, La version concise n'est pas parfaite, simplement la meilleure que j'ai trouvée. Il est censé être pratique et ne pas englober tout. Notez que la valeur renvoyée par votre boolne se transforme en 0. De plus, vous êtes découragé de créer des surcharges incohérentes et les valeurs que vous renvoyez peuvent être considérées comme telles. (Par exemple, un &&peut être optimisé en un ||, donc si ceux-ci n'étaient pas cohérents, vous auriez un problème.)
ikegami
Je ne sais pas si 0x00est couvert ici.
Zaid
@Zaid, voulez-vous dire la valeur renvoyée par le code 0x00(la valeur numérique zéro) ou la chaîne 0x00(pour laquelle looks_like_numberest faux)? De toute façon, c'est déjà couvert.
ikegami
59

Perl n'a pas de type booléen natif, mais vous pouvez utiliser la comparaison d'entiers ou de chaînes afin d'obtenir le même comportement. L'exemple d'Alan est une belle façon de le faire en utilisant la comparaison d'entiers. Voici un exemple

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

Une chose que j'ai faite dans certains de mes programmes est d'ajouter le même comportement en utilisant une 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";
}

Les lignes marquées "use constant" définissent une constante nommée true qui évalue toujours à 1 et une constante nommée false qui évalue toujours par 0. En raison de la façon dont les constantes sont définies en Perl, les lignes de code suivantes échouent également:

true = 0;
true = false;

Le message d'erreur doit dire quelque chose comme «Impossible de modifier la constante dans l'affectation scalaire».

Je l'ai vu dans l'un des commentaires que vous avez demandé sur la comparaison des chaînes. Vous devez savoir que parce que Perl combine des chaînes et des types numériques dans des variables scalaires, vous avez une syntaxe différente pour comparer les chaînes et les nombres:

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 différence entre ces opérateurs est une source de confusion très courante en Perl.

James Thompson
la source
5
use warnings;au lieu de#! perl -w
Brad Gilbert
11
Il est dangereux d'utiliser des constantes comme macros d'un homme pauvre de cette façon. Ces exemples de code ne sont pas équivalents: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, qui pourrait ne pas être évident pour un observateur occasionnel. (Et oui, le dernier exemple est un mauvais style de programmation, mais c'est à côté du point).
Zano
16

Je recommande use boolean;. Vous devez cependant installer le module booléen depuis cpan.

xénoterracide
la source
7
En Perl, comme dans la vie, il y a beaucoup de vérités. Les inexpérimentés aiment écrire des choses idiotes comme if ($my_true_value == true). Prétendre qu'il existe une seule vraie vérité est, selon mon expérience, un chemin vers la douleur et un code inefficace.
tjd
2
Perl est philosophique par nature
ILMostro_7
13

Mes favoris ont toujours été

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

qui est complètement indépendant de la représentation interne.

syck
la source
5
Brillant. Vous avez à vous seul corrigé le langage de programmation Perl!
Nostalg.io
8

Je suis tombé sur un tutoriel qui a une bonne explication sur les valeurs vraies et fausses en Perl . Il déclare que:

Les valeurs scalaires suivantes sont considérées comme fausses:

  • undef - la valeur indéfinie
  • 0 le nombre 0, même si vous l'écrivez en 000 ou 0,0
  • '' la chaîne vide.
  • '0' la chaîne qui contient un seul chiffre 0.

Toutes les autres valeurs scalaires, y compris les suivantes, sont vraies:

  • 1 tout numéro différent de 0
  • ' ' la chaîne avec un espace
  • '00' deux ou plusieurs 0 caractères dans une chaîne
  • "0\n" un 0 suivi d'une nouvelle ligne
  • 'true'
  • 'false' oui, même la chaîne 'false' a la valeur true.

Il existe un autre bon tutoriel qui explique le vrai et le faux de Perl .

serenesat
la source
6

Belle explication donnée par bobf pour les valeurs booléennes: Vrai ou faux? Un guide de référence rapide

Tests de vérité pour différentes valeurs

                       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
la source
Mauvaise réponse, mais une source solide et réputée sur perlmonks.org. Ce serait bien d'avoir du vrai contenu au lieu d'un commentaire et d'un lien. : - /
ILMostro_7
0

utilisez le préfixe de fichier suivant, cela ajoutera à votre script perl eTRUE et eFALSE, ce sera en fait REAL (!) vrai et faux (tout comme 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' )
             };

Il y a, en fait, peu de raisons pour lesquelles vous devriez utiliser cela.

Ma raison est qu'en travaillant avec JSON, j'ai 0 et 1 comme valeurs pour les clés, mais ce hack s'assurera que les valeurs correctes sont conservées tout au long de votre script.


la source