Frage

Kann mir jemand erklären, was genau die Zeichenkette „0, aber wahr“ bedeutet in Perl? Soweit ich verstehe, entspricht es Null in einem ganzzahligen Vergleich, aber wahr ausgewertet, wenn sie als boolean verwendet. Ist das richtig? Ist das ein normales Verhalten der Sprache oder ist dies eine besondere Zeichenfolge als Sonderfall im Interpreter behandelt?

War es hilfreich?

Lösung

Es ist ein normales Verhalten der Sprache. Zitiert von der perlsyn manpage:

  

Die Zahl 0, die Saiten '0' und "", die leere Liste () und undef   alle falsch sind in einem Booleschen Kontext. Alle anderen Werte sind wahr. Negation   von einem wahren Wert von ! oder not gibt einen speziellen falschen Wert.   Wenn sie als Zeichenfolge ausgewertet wird es als "" behandelt, sondern als eine Zahl, es ist   behandelt wie 0.

Aus diesem Grunde muss es eine Möglichkeit geben 0 von einem Systemaufruf zurückzugeben, die 0 als (erfolgreich) Rückgabewert zurück erwartet, und lassen Sie einen Weg, um einen Fehlerfall zu signalisieren, indem tatsächlich einen falschen Wert zurück. "0 but true" dient diesem Zweck.

Andere Tipps

Weil es in dem Perl-Kern fest einprogrammiert ist es als eine Zahl zu behandeln. Dies ist ein Hack in Perl Konventionen und ioctl Konventionen spielen zusammen zu machen; von perldoc -f ioctl:

  

Der Rückgabewert von ioctl (und fcntl) ist wie folgt:

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number
     

So gibt Perl bei Erfolg true false bei einem Fehler, aber Sie   bestimmen immer noch leicht den tatsächlichen Wert zurückgegeben wird, kann durch die   Betriebssystem:

$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;
     

Die spezielle String "0 but true" ist frei von -w Beschwerden   über falsche numerische Konvertierungen.

Zusätzlich zu dem, was andere gesagt, "0 but true" ist für eine spezielle verrohrt, dass sie nicht in einem numerischen Kontext warnen:

$ perl -wle 'print "0 but true" + 3'
3
$ perl -wle 'print "0 but crazy" + 3'
Argument "0 but crazy" isn't numeric in addition (+) at -e line 1.
3

Der Wert 0 but true ist ein Sonderfall in Perl. Obwohl auf Ihre Sterblicher Augen, sieht es nicht wie eine Nummer, weise und allwissend Perl versteht es wirklich eine Zahl ist.

Es hat mit der Tatsache zu tun, dass, wenn ein Perlfunktionen einen 0-Wert zurückgibt, wird angenommen, dass die Routine versagt oder zurück einen falschen Wert.

Stellen Sie sich vor mir ein Unterprogramm habe, dass die Summe von zwei Zahlen zurück:

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));

Die erste Anweisung wird nicht sterben, weil das Unterprogramm eine 1 zurück. Das ist gut. Die zweite Anweisung wird sterben, weil das Unterprogramm nicht in der Lage sein, zu addieren Kuh Hund .

Und die dritte Aussage?

Hmmm, kann ich hinzufügen 3 -3. Bekomme ich nur 0, aber dann wird mein Programm sterben, obwohl das add Unterprogramm gearbeitet!

Um dies zu umgehen, Perl hält 0 but true eine Zahl zu sein. Wenn mein in Unterprogramm kehrt nicht nur 0 , sondern 0, aber wahr , meine dritte Anweisung funktioniert.

Aber ist 0, aber wahr numerisch Null? Versuchen Sie diese:

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

Yup, es ist null!

Der Index Unterroutine rel="noreferrer"> 0, aber wahr war um. Es wird angenommen, um die Position des Teils in der Zeichenfolge befand zurückzukehren:

index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...

Die letzte statment gibt einen -1. Was bedeutet, wenn ich dies tat:

if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}

Als ich in der Regel mit Standard-Funktionen zu tun, würde es nicht funktionieren. Wenn ich „barfoo“ verwendet und „bar“, wie ich in der zweiten Anweisung täte, würde die else Klausel ausführen, aber wenn ich „barfoo“ verwendet und „fu“, wie er in den dritten, würde die if Klausel auszuführen. Nicht das, was ich will.

Wenn jedoch das index Unterprogramm zurückgegeben 0, aber wahr für die zweite Anweisung und undef für die dritte Aussage, meine if / else Klausel funktioniert habe.

Sie können auch die Zeichenfolge "0E0" verwendet in Perl-Code , und es bedeutet das gleiche, wo 0E0 bedeutet nur 0 in Exponentialnotation geschrieben. da Perl nur Allerdings hält „0“, ‚‘ oder undef als falsch wertet es auf true in einem Booleschen Kontext.

Es ist hart codiert in Perl-Quellcode, speziell in Perl_grok_number_flags in numeric.c .

, dass Code Lese entdeckte ich, dass die Zeichenfolge „unendlich“ (Groß- und Kleinschreibung) zu den looks_like_number Test besteht. Ich hatte das nicht bekannt.

In einem ganzzahligen Zusammenhang wertet sie auf 0 (dem numerischen Teil am Anfang des Strings) und ist gleich Null. In einem skalaren Kontext ist es ein nicht-leerer Wert, so dass es wahr ist.

  • if (int("0 but true")) { print "zero"; }

    (keine Ausgabe)

  • if ("0 but true") { print "true"; }

    (prints true)

0 bedeutet falsch in Perl (und anderen C verwandten Sprachen). Zum größten Teil, das ist ein vernünftiges Verhalten. Andere Sprachen (Lua zum Beispiel) 0 als wahr behandeln und bietet eine weiteren Token (oft nil oder false ) einen nicht-wahren Wert zu repräsentieren.

Ein Fall, in dem die Perl Art und Weise nicht so gut funktioniert, wenn Sie entweder eine Zahl oder zurückgeben möchten, wenn die Funktion aus irgendeinem Grund fehlschlägt, einen falschen Wert. Zum Beispiel, wenn Sie schreiben eine Funktion, die eine Zeile aus einer Datei liest und gibt die Anzahl der Zeichen in der Zeile. Eine gemeinsame Nutzung der Funktion könnte so etwas wie:

while($c = characters_in_line($file)){
    ...
};

Beachten Sie, dass, wenn die Anzahl der Zeichen auf einer bestimmten Zeile ist 0, die , während Schleife vor dem Ende der Datei enden wird. So ist die characters_in_line Funktion sollte Sonderfall 0 Zeichen und zurück '0 aber wahr' statt. Auf diese Weise wird die Funktion wie in dem sollte arbeiten, während Schleife, sondern auch die richtige Antwort zurückgeben sollte es als Nummer verwendet werden.

Beachten Sie, dass dies nicht ein Teil der Sprache aufgebaut ist. Vielmehr nutzt er die von Perl Fähigkeit, eine Zeichenfolge als Zahl zu interpretieren. So werden manchmal andere Stiche verwendet statt. DBI verwendet "0E0" , zum Beispiel. Wenn in einem numerischen Kontext ausgewertet, kehren sie 0 , aber in Booleschen Kontext, false .

Dinge, die falsch sind:

  • "".
  • "0".
  • Dinge, die die stringify.

"0 but true" ist nicht einer von denen, so ist es nicht falsch ist.

Darüber hinaus gibt Perl "0 but true", wo eine Reihe, um zu erwarten, um zu signalisieren, dass eine Funktion gelang es, auch wenn es wieder Null. sysseek ist ein Beispiel für eine solche Funktion. Da der Wert als Zahl erwartet wird verwendet, wird Perl codiert es zu betrachten, eine Zahl zu sein. Als Ergebnis, werden keine Warnungen ausgegeben, wenn es als Nummer verwendet wird, und looks_like_number("0 but true") gibt true zurück.

Andere "true Nullen" können unter http://www.perlmonks.org/?node_id finden = 464.548 .

Ein weiteres Beispiel für "0, aber wahr":

Das DBI-Modul verwendet „0E0“ als Rückgabewert für UPDATE oder DELETE-Abfragen, die keine Datensätze nicht beeinträchtigten. Er wertet auf true in einem Booleschen Kontext (was anzeigt, dass die Abfrage wurde ordnungsgemäß ausgeführt wird) und auf 0 in einem numerischen Kontext anzeigt, dass keine Datensätze von der Abfrage verändert wurden.

Ich habe gerade Beweis dafür, dass die Zeichenkette „0, aber wahr“ tatsächlich in die Interpreter eingebaut ist, wie einige Leute hier schon beantwortet:

$ strings /usr/lib/perl5/5.10.0/linux/CORE/libperl.so | grep -i true
Perl_sv_true
%-p did not return a true value
0 but true
0 but true

Wenn Sie eine Funktion schreiben wollen, die entweder einen Integer-Wert zurückgibt, oder false oder undef (dh für den Fehlerfall), dann müssen Sie für die achten Wert Null. Wiederkehr es falsch ist, und soll die Fehlerbedingung nicht angeben, so „0, aber wahr“ Rückkehr macht die Funktion Rückgabewert true, während immer noch wieder den Wert Null vorbei, wenn Mathe auf es gemacht wird.

„0, aber wahr“ ist eine Zeichenfolge, wie jede andere, sondern weil der Perl-Syntax es einen nützlichen Zweck dienen kann, nämlich ganze Zahl Rückkehr Null aus einer Funktion, ohne das Ergebnis zu sein „false“ (in Perl-Augen).

Und die Zeichenfolge muss nicht sein „0, aber wahr“. "0, aber falsch" ist immer noch "true" im boolean Sinne.

betrachten:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false

Das Ergebnis all dessen ist man haben kann:

sub find_x()

und habe diesen Code in der Lage „0“ als Ausgabe drucken:

if($x = find_x)
{
   print int($x) . "\n";
}

Der String `` 0, aber wahr '' ist nach wie vor ein Sonderfall:

for arg in "'0 but true'" "1.0*('0 but true')" \
           "1.0*('0 but false')" 0 1 "''" "0.0" \
           "'false'" "'Ja'" "'Nein'" "'Oui'" \
           "'Non'" "'Yes'" "'No'" ;do
    printf "%-32s: %s\n" "$arg" "$(
        perl -we '
            my $ans=eval $ARGV[0];
            $ans=~s/^(Non?|Nein)$//;
            if ($ans) {
                printf "true:  |%s|\n",$ans
            } else {
                printf "false: |%s|", $ans
          };' "$arg"
        )"
    done

geben Sie den folgenden: (! Beachten Sie die `` Warnung '')

'0 but true'                    : true:  |0 but true|
1.0*('0 but true')              : false: |0|
Argument "0 but false" isn't numeric in multiplication (*) at (eval 1) line 1.
1.0*('0 but false')             : false: |0|
0                               : false: |0|
1                               : true:  |1|
''                              : false: ||
0.0                             : false: |0|
'false'                         : true:  |false|
'Ja'                            : true:  |Ja|
'Nein'                          : false: ||
'Oui'                           : true:  |Oui|
'Non'                           : false: ||
'Yes'                           : true:  |Yes|
'No'                            : false: ||

... und vergessen Sie nicht RTFM!

man -P'less +"/0 but [a-z]*"' perlfunc

       ... "fcntl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.  This string is true in boolean
           context and 0 in numeric context.  It is also exempt from the
           normal -w warnings on improper numeric conversions. ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top