Jak używać zmiennych boolowskich w Perlu?

220

Próbowałem:

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

Żadna z tych czynności nie działa. Pojawia się komunikat o błędzie

Bareword „false” jest niedozwolony podczas używania „ścisłych napisów”.
Chad DeShon
źródło
37
Możesz zacząć od mojej książki Learning Perl . To łatwiejsze niż zgadywanie, co zrobić, dopóki nie zrobisz tego dobrze (małpy, maszyny do pisania, Hamlet i tak dalej). :)
brian d foy

Odpowiedzi:

285

W Perlu następujące wartości warunkowe są fałszywe:

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

Reszta jest prawdą. Brak słów kluczowych dla truelub false.

Alan Haggai Alavi
źródło
2
@BlueWaldo: możesz także używać cmp i <=> podczas porównywania i przypisywania wyników porównania do skalara. $ var = $ var1 cmp $ var2; „cmp” i „<=>” (używane do porównań numerycznych) zwracają -1, 0 lub 1, jeśli lewy argument jest mniejszy, równy lub większy niż prawy argument. Nie jest to wartość logiczna, ale czasami możesz chcieć wiedzieć, czy jeden argument jest równy lub mniejszy lub większy niż drugi zamiast po prostu równy lub nie równy.
user118435
9
Problem 1: Pusta lista nie jest fałszywa, ponieważ nie można sprawdzić, czy lista jest prawdziwa czy fałszywa. Zwraca pusta lista w kontekście skalarnym undef.
ikegami,
4
Problem 2: ('')i ''mają tę samą wartość. Myślę, że chciałeś sugerować listę z elementem składającym się z pustego łańcucha (nawet jeśli pareny nie tworzą list), ale jak już wspomniałem, nie można sprawdzić, czy lista jest prawdziwa z fałszem.
ikegami,
6
Problem 3: Obiekty z przeciążonym operatorem logicznym mogą być również fałszywe.
ikegami,
15
@eternicode, Perl ma dwie określone wartości, których używa, gdy musi zwracać wartość prawda i fałsz, więc nie tylko ma logiczne wartości, ale także prawda ( !0aka PL_sv_yes) i fałsz ( !1aka PL_sv_no). A może mówisz, że Perl powinien skakać, ilekroć coś innego niż te dwie wartości jest sprawdzane pod kątem prawdziwości? To byłoby całkowicie okropne. np. To zapobiegłoby$x ||= $default;
ikegami
71

Najbardziej kompletna, zwięzła definicja fałszu, na jaką natrafiłem, to:

Wszystko, co zawiera pusty ciąg lub ciąg, 0jest fałszywe. Wszystko inne jest prawdą.

Dlatego następujące wartości są fałszywe:

  • Pusty ciąg
  • Wartość liczbowa zero
  • Nieokreślona wartość
  • Obiekt z przeciążonym operatorem logicznym, który ocenia jeden z powyższych.
  • Magiczna zmienna, która przy pobieraniu ocenia jedną z powyższych.

Należy pamiętać, że pusty literał listy ocenia na wartość nieokreśloną w kontekście skalarnym, więc zwraca wartość fałszywą.


Uwaga na temat „prawdziwych zer”

Podczas gdy liczby, które są oznaczane jako 0fałsz, są fałszywe, ciągi, które numerują do zera, niekoniecznie. Jedyne fałszywe ciągi to 0pusty ciąg. Każdy inny ciąg znaków, nawet jeśli ma wartość zero, jest prawdziwy.

Poniżej przedstawiono ciągi znaków, które są prawdziwe jako wartość logiczna, a zero jako liczba:

  • Bez ostrzeżenia:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Z ostrzeżeniem:
    • Dowolny ciąg znaków, dla którego Scalar::Util::looks_like_numberzwraca wartość false. (np. "abc")
ikegami
źródło
jeśli dobrze zrozumiałem, słowo prawda w Chociaż liczby, które oznaczają 0 są prawdą, powinno być fałszywe lub (aby zapobiec pomyłkom) ocenić na fałszywe .
user907860,
1
Twoja „zwięzła” definicja jest niezgodna z dłuższym wyjaśnieniem. Rozważmy: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Teraz $valueskretyfikuje do „XXX”, ale loguje się w false.
tobyink
1
@tobyink, Zwięzła wersja nie jest idealna, tylko najlepsza, jaką znalazłem. Ma być praktyczny, a nie wszechstronny. Zwróć uwagę, że wartość zwrócona przez twoja boolstringify to 0. Ponadto odradza się tworzenie niespójnych przeciążeń, a zwracane wartości można uznać za takie. (np. &&można zoptymalizować w a ||, więc gdyby były niespójne, miałbyś problem).
ikegami
Nie jestem pewien, czy 0x00jest tutaj objęty.
Zaid
@Zaid, Czy masz na myśli wartość zwróconą przez kod 0x00(wartość liczbowa zero) lub ciąg znaków 0x00(dla których looks_like_numberjest fałsz)? Tak czy inaczej, jest już objęty.
ikegami,
59

Perl nie ma rodzimego typu logicznego, ale można użyć porównania liczb całkowitych lub ciągów, aby uzyskać takie samo zachowanie. Przykład Alana jest dobrym sposobem na to, używając porównania liczb całkowitych. Oto przykład

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

Jedną rzeczą, którą zrobiłem w niektórych moich programach, jest dodanie tego samego zachowania przy użyciu stałej:

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

Linie oznaczone jako „użyj stałej” definiują stałą o nazwie prawda, która zawsze ma wartość 1, oraz stałą o nazwie fałsz, która zawsze ma wartość 0. Ze względu na sposób, w jaki stałe są definiowane w Perlu, następujące wiersze kodu również zawodzą:

true = 0;
true = false;

Komunikat o błędzie powinien brzmieć „Nie można zmodyfikować stałej w przypisaniu skalarnym”.

Widziałem to w jednym z komentarzy, które pytałeś o porównywanie ciągów. Powinieneś wiedzieć, że ponieważ Perl łączy ciągi i typy liczbowe w zmiennych skalarnych, masz inną składnię do porównywania ciągów i liczb:

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

Różnica między tymi operatorami jest bardzo powszechnym źródłem nieporozumień w Perlu.

James Thompson
źródło
5
use warnings;zamiast#! perl -w
Brad Gilbert
11
Używanie w ten sposób stałych jako słabych makr jest niebezpieczne. Te przykłady kodu nie są równoważne: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, co może nie być oczywiste dla zwykłego obserwatora. (I tak, ostatnim przykładem jest kiepski styl programowania, ale to nie ma znaczenia).
Zano,
16

Polecam use boolean;. Musisz jednak zainstalować moduł boolean z cpan.

ksenoterracid
źródło
7
W Perlu, podobnie jak w życiu, istnieje wiele prawd. Niedoświadczeni lubią pisać głupie rzeczy if ($my_true_value == true). Udawanie, że istnieje Jedna Prawdziwa Prawda, jest, z mojego doświadczenia, ścieżką do bólu i nieefektywnym kodem.
tjd
2
Perl jest z natury filozoficzny
ILMostro_7,
13

Moimi ulubionymi zawsze byli

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

który jest całkowicie niezależny od wewnętrznej reprezentacji.

syk
źródło
5
Znakomity. Naprawiłeś język programowania Perl w pojedynkę!
Nostalg.io,
8

Natknąłem się na samouczek, który dobrze wyjaśnia, jakie wartości są prawdziwe i fałszywe w Perlu . Stwierdza, że:

Następujące wartości skalarne są uważane za fałszywe:

  • undef - niezdefiniowana wartość
  • 0 liczba 0, nawet jeśli napiszesz jako 000 lub 0,0
  • '' pusty ciąg.
  • '0' ciąg zawierający jedną cyfrę 0.

Wszystkie inne wartości skalarne, w tym następujące, są prawdziwe:

  • 1 dowolna liczba inna niż 0
  • ' ' ciąg ze spacją
  • '00' dwa lub więcej 0 znaków w ciągu
  • "0\n" 0, po której następuje nowa linia
  • 'true'
  • 'false' tak, nawet ciąg „false” zwraca wartość true.

Jest jeszcze jeden dobry samouczek, który wyjaśnia, jak Perl jest prawdziwy i fałszywy .

serenesat
źródło
6

Piękne wyjaśnienie podane przez bobf dla wartości boolowskich: prawda czy fałsz? Skrócona instrukcja obsługi

Testy prawdy dla różnych wartości

                       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
źródło
Słaba odpowiedź, ale silne, renomowane źródło w perlmonks.org. Byłoby miło mieć prawdziwą treść zamiast komentarza i linku. : - /
ILMostro_7
0

użyj następującego przedrostka pliku, to doda do twojego skryptu perla eTRUE i eFALSE, w rzeczywistości będzie to PRAWDZIWE (!) prawdziwe i fałszywe (tak jak 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' )
             };

Jest tak naprawdę kilka powodów, dla których powinieneś tego używać.

Moim powodem jest to, że pracując z JSON, mam 0 i 1 jako wartości kluczy, ale ten hack upewni się, że prawidłowe wartości są zachowane wzdłuż twojego skryptu.


źródło