Wie verwende ich boolesche Variablen in Perl?


220

Ich habe versucht:

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

Keine dieser Arbeiten. Ich erhalte die Fehlermeldung

Barwort "false" ist nicht zulässig, solange "strict subs" verwendet wird.

37
Vielleicht möchten Sie mit meinem Buch Learning Perl beginnen . Es ist einfacher als zu raten, was zu tun ist, bis Sie es richtig verstanden haben (Affen, Schreibmaschinen und Hamlet und all das). :)
Brian D Foy

Antworten:


285

In Perl wird Folgendes unter Bedingungen als falsch bewertet:

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

Der Rest ist wahr. Es gibt keine Barwörter für trueoder false.


2
@BlueWaldo: Sie können auch cmp und <=> verwenden, um die Ergebnisse des Vergleichs zu vergleichen und einem Skalar zuzuweisen. $ var = $ var1 cmp $ var2; 'cmp' und '<=>' (für numerische Vergleiche verwendet) geben -1, 0 oder 1 zurück, wenn das linke Argument kleiner, gleich oder größer als das rechte Argument ist. Es ist nicht boolesch, aber manchmal möchten Sie vielleicht wissen, ob ein Argument gleich oder kleiner oder größer als das andere ist, anstatt nur gleich oder nicht gleich.
user118435

9
Problem 1: Eine leere Liste ist nicht falsch, da nicht überprüft werden kann, ob eine Liste wahr oder falsch ist. Eine leere Liste im skalaren Kontext wird zurückgegeben undef.
Ikegami

4
Problem 2: ('')und ''sind der gleiche Wert. Ich denke, Sie wollten eine Liste mit einem Element implizieren, das aus einer leeren Zeichenfolge besteht (obwohl Parens keine Listen erstellen), aber wie ich bereits erwähnt habe, ist es unmöglich zu überprüfen, ob eine Liste wahr oder falsch ist.
Ikegami

6
Problem 3: Objekte mit einem überladenen booleschen Operator können ebenfalls falsch sein.
Ikegami

15
@eternicode, Perl hat zwei spezifische Werte, die es verwendet, wenn es true und false zurückgeben muss. Es hat also nicht nur Boolesche Werte, sondern auch true ( !0aka PL_sv_yes) und false ( !1aka PL_sv_no). Oder sagen Sie, Perl sollte krächzen, wenn etwas anderes als diese beiden Werte auf Wahrhaftigkeit geprüft werden? Das wäre völlig schrecklich. zB würde es verhindern$x ||= $default;
Ikegami

71

Die vollständigste und prägnanteste Definition von falsch ist mir begegnet:

Alles, was mit der leeren Zeichenfolge oder der Zeichenfolge verknüpft wird, 0ist falsch. Alles andere ist wahr.

Daher sind die folgenden Werte falsch:

  • Die leere Zeichenfolge
  • Zahlenwert Null
  • Ein undefinierter Wert
  • Ein Objekt mit einem überladenen booleschen Operator, der einen der oben genannten Werte auswertet.
  • Eine magische Variable, die beim Abrufen als eine der oben genannten Variablen ausgewertet wird.

Beachten Sie, dass ein leeres Listenliteral im skalaren Kontext einen undefinierten Wert ergibt, sodass es einen falschen Wert ergibt.


Ein Hinweis zu "wahren Nullen"

Während Zahlen, zu denen eine Zeichenfolge führt, 0falsch sind, sind Zeichenfolgen, die zu Null nummerieren, nicht unbedingt falsch. Die einzigen falschen Zeichenfolgen sind 0und die leere Zeichenfolge. Jede andere Zeichenfolge, auch wenn sie auf Null nummeriert ist, ist wahr.

Die folgenden Zeichenfolgen sind als Boolescher Wert und als Zahl als Null wahr:

  • Ohne Vorwarnung:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Mit einer Warnung:
    • Jede Zeichenfolge, für die Scalar::Util::looks_like_numberfalse zurückgegeben wird. (zB "abc")

Wenn ich verstanden habe, dass Sie richtig sind, sollte das Wort wahr in Während Zahlen, die auf 0 gesetzt sind, wahr sind, falsch sein oder (um Verwirrung zu vermeiden) als falsch bewertet werden .
user907860

1
Ihre "prägnante" Definition stimmt nicht mit Ihrer längeren Erklärung überein. Bedenken Sie : my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Jetzt $valuewird auf "XXX" gesetzt, aber auf false boolifiziert.
tobyink

1
@tobyink, Die prägnante Version ist nicht perfekt, nur die beste, die ich gefunden habe. Es soll praktisch sein, nicht allumfassend. Beachten Sie, dass der von Ihrem zurückgegebene Wert eine boolZeichenfolge enthält 0. Sie werden auch davon abgehalten, inkonsistente Überladungen zu erstellen, und die von Ihnen zurückgegebenen Werte können als solche angesehen werden. (zB &&kann a in a optimiert werden. ||Wenn diese also inkonsistent wären, hätten Sie ein Problem.)
Ikegami

Ich bin mir nicht sicher, ob 0x00hier behandelt wird.
Zaid

@Zaid, Meinst du den vom Code zurückgegebenen 0x00Wert (der numerische Wert Null) oder die Zeichenfolge 0x00(für die looks_like_numberfalsch ist)? In jedem Fall ist es bereits abgedeckt.
Ikegami

59

Perl hat keinen nativen booleschen Typ, aber Sie können Ganzzahlen oder Zeichenfolgen vergleichen, um das gleiche Verhalten zu erzielen. Alans Beispiel ist eine gute Möglichkeit, dies durch den Vergleich von ganzen Zahlen zu tun. Hier ist ein Beispiel

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

Eine Sache, die ich in einigen meiner Programme getan habe, ist das gleiche Verhalten unter Verwendung einer Konstante:

#!/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";
}

Die unter "Konstante verwenden" markierten Zeilen definieren eine Konstante mit dem Namen true, die immer mit 1 ausgewertet wird, und eine Konstante mit dem Namen false, die immer mit 0 bewertet wird. Aufgrund der Art und Weise, wie Konstanten in Perl definiert werden, schlagen auch die folgenden Codezeilen fehl:

true = 0;
true = false;

Die Fehlermeldung sollte etwa "Konstante in Skalarzuweisung kann nicht geändert werden" lauten.

Ich habe das in einem der Kommentare gesehen, die Sie zum Vergleichen von Zeichenfolgen angefordert haben. Da Perl Zeichenfolgen und numerische Typen in skalaren Variablen kombiniert, sollten Sie wissen, dass Sie unterschiedliche Syntax zum Vergleichen von Zeichenfolgen und Zahlen haben:

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";
}

Der Unterschied zwischen diesen Operatoren ist eine sehr häufige Quelle der Verwirrung in Perl.


5
use warnings;statt#! perl -w
Brad Gilbert

11
Die Verwendung von Konstanten als Makros für arme Männer auf diese Weise ist gefährlich. Diese Codebeispiele sind nicht gleichwertig: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, was für einen zufälligen Beobachter möglicherweise nicht offensichtlich ist. (Und ja, das letzte Beispiel ist ein schlechter Programmierstil, aber das ist nebensächlich).
Zano

16

Ich empfehle use boolean;. Sie müssen das boolesche Modul jedoch von cpan aus installieren.


7
In Perl wie im Leben gibt es viele Wahrheiten. Die Unerfahrenen schreiben gerne alberne Sachen wie if ($my_true_value == true). Das Vorgeben, dass es eine wahre Wahrheit gibt, ist meiner Erfahrung nach ein Weg zum Schmerz und ineffizienter Code.
4.

2
Perl ist von Natur aus philosophisch
ILMostro_7

13

Meine Favoriten waren schon immer

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

das ist völlig unabhängig von der internen Darstellung.


5
Brillant. Sie haben die Perl-Programmiersprache im Alleingang repariert!
Nostalg.io

8

Ich bin auf ein Tutorial gestoßen, das gut erklärt, welche Werte in Perl wahr und was falsch sind . Darin heißt es:

Folgende Skalarwerte gelten als falsch:

  • undef - der undefinierte Wert
  • 0 die Zahl 0, auch wenn Sie sie als 000 oder 0,0 schreiben
  • '' die leere Zeichenfolge.
  • '0' Die Zeichenfolge, die eine einzelne 0-Ziffer enthält.

Alle anderen Skalarwerte, einschließlich der folgenden, sind wahr:

  • 1 eine beliebige Nicht-0-Zahl
  • ' ' die Zeichenfolge mit einem Leerzeichen
  • '00' zwei oder mehr 0 Zeichen in einer Zeichenfolge
  • "0\n" eine 0 gefolgt von einem Zeilenumbruch
  • 'true'
  • 'false' Ja, sogar die Zeichenfolge 'false' wird als true ausgewertet.

Es gibt ein weiteres gutes Tutorial, das Perl als wahr und falsch erklärt .


6

Schöne Erklärung von bobf für boolesche Werte: Richtig oder falsch? Eine Kurzanleitung

Wahrheitstests für verschiedene Werte

                       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

Schlechte Antwort, aber eine starke, seriöse Quelle in perlmonks.org. Es wäre schön, echte Inhalte anstelle eines Kommentars und eines Links zu haben. : - /
ILMostro_7

0

Verwenden Sie das folgende Dateipräfix. Dies wird Ihrem Perl-Skript eTRUE und eFALSE hinzugefügt. Es ist tatsächlich REAL (!) true und false (genau wie 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' )
             };

Es gibt eigentlich nur wenige Gründe, warum Sie das verwenden sollten.

Mein Grund ist, dass ich bei der Arbeit mit JSON 0 und 1 als Werte für Schlüssel habe, aber dieser Hack stellt sicher, dass die korrekten Werte in Ihrem Skript beibehalten werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.