Quelqu'un peut-il expliquer ce que signifie exactement la chaîne "0 mais vrai" en Perl ? D'après ce que je comprends, elle est égale à zéro dans une comparaison d'entiers, mais évalue à vrai lorsqu'elle est utilisée comme booléen. Est-ce correct ? S'agit-il d'un comportement normal du langage ou d'une chaîne spéciale traitée comme un cas particulier dans l'interpréteur ?
Réponses
Trop de publicités?C'est un comportement normal de la langue. En citant le perlsyn
page de manuel :
Le nombre 0, les chaînes '0' et '', la liste vide "()", et "undef" sont tous faux dans un contexte booléen. Toutes les autres valeurs sont vraies. Négation d'une valeur vraie par " !" ou "not" renvoie une valeur fausse spéciale. Lorsqu'elle est évaluée en tant que chaîne, elle est traitée comme '', mais en tant que nombre, elle est traité comme 0.
Pour cette raison, il doit y avoir un moyen de renvoyer 0 à partir d'un appel système qui s'attend à renvoyer 0 comme valeur de retour (réussie), et laisser un moyen de signaler un cas d'échec en renvoyant réellement une valeur fausse. "0 but true"
sert cet objectif.
Parce qu'il est codé en dur dans le noyau Perl pour le traiter comme un nombre. Il s'agit d'un hack pour rendre les conventions de Perl et les ioctl
Les conventions de l'UE jouent ensemble ; de perldoc -f ioctl
:
La valeur de retour de
ioctl
(yfcntl
) est le suivant :if OS returns: then Perl returns: -1 undefined value 0 string "0 but true" anything else that number
Ainsi, Perl renvoie vrai en cas de succès et faux en cas d'échec, mais vous pouvez pourtant, vous pouvez facilement déterminer la valeur réelle retournée par le système d'exploitation :
$retval = ioctl(...) || -1; printf "System returned %d\n", $retval;
La chaîne spéciale
"0 but true"
est exemptée de-w
plaintes concernant des conversions numériques incorrectes.
La valeur 0 but true
est un cas particulier en Perl. Bien que pour vos simples yeux de mortel, cela ne ressemble pas à un nombre, Perl, sage et omniscient, comprend que c'est vraiment un nombre.
Cela est dû au fait que lorsqu'une sous-routine Perl renvoie une valeur 0, on suppose que la routine a échoué ou a renvoyé une valeur fausse.
Imaginez que j'ai une sous-routine qui renvoie la somme de deux nombres :
die "You can only add two numbers\n" if (not add(3, -2));
die "You can only add two numbers\n" if (not add("cow", "dog"));
die "You can only add two numbers\n" if (not add(3, -3));
La première déclaration ne mourra pas parce que la sous-routine renverra une valeur de 1
. C'est bien. La deuxième instruction mourra parce que la sous-routine ne pourra pas additionner vache a chien .
Et, la troisième déclaration ?
Hmmm, je peux ajouter 3
a -3
. J'ai juste 0
mais mon programme mourra alors, même si l'option add
La sous-routine a fonctionné !
Pour contourner ce problème, Perl considère 0 but true
pour être un nombre. Si mon ajouter La sous-routine retourne non seulement 0 mais 0 mais vrai ma troisième déclaration fonctionnera.
Mais est-ce que 0 mais vrai un zéro numérique ? Essayez ceci :
my $value = "0 but true";
print qq(Add 1,000,000 to it: ) . (1_000_000 + $value) . "\n";
print "Multiply it by 1,000,000: " . 1_000_000 * $value . "\n";
Oui, c'est zéro !
El indice est un très vieux morceau de Perl et existait avant le concept de 0 mais vrai était dans le coin. Elle est censée renvoyer la position de la sous-chaîne située dans la chaîne :
index("barfoo", "foo"); #This returns 3
index("barfoo", "bar"); #This returns 0
index("barfoo", "fu"); #This returns ...uh...
Le dernier statut renvoie un -1
. Ce qui veut dire que si je faisais ça :
if ($position = index($string, $substring)) {
print "It worked!\n";
}
else {
print "If failed!\n";
}
Comme je le fais habituellement avec les fonctions standard, cela ne fonctionnait pas. Si j'utilisais "barfoo" et "bar" comme je l'ai fait dans la deuxième instruction, la fonction else
s'exécuterait, mais si j'utilisais "barfoo" et "fu" comme dans la troisième, la clause if
s'exécuterait. Ce n'est pas ce que je veux.
Toutefois, si le index
sous-programme retourné 0 mais vrai pour la deuxième déclaration et undef
pour la troisième déclaration, mon if
/ else
aurait fonctionné.
Vous pouvez également voir la chaîne "0E0" utilisé dans le code Perl et cela signifie la même chose, alors que 0E0 signifie simplement 0 écrit en notation exponentielle. Cependant, puisque Perl ne considère que "0", '' ou undef comme faux, il est évalué à vrai dans un contexte booléen.