Perl'de boole değişkenlerini nasıl kullanırım?


220

Denedim:

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

Bunların hiçbiri işe yaramıyor. Hata mesajını alıyorum

Bareword "false", "katı subs" kullanımdayken izin verilmez.

37
Benim Öğrenme Perl kitabımla başlamak isteyebilirsiniz . Doğru olana kadar ne yapacağınızı tahmin etmekten daha kolaydır (maymunlar, daktilolar ve Hamlet ve diğerleri). :)
brian d foy

Yanıtlar:


285

Perl'de, aşağıdaki şartlar altında yanlış olarak değerlendirilir:

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

Gerisi doğrudur. Hiçbir barewords vardır trueya false.


2
@MaviWaldo: karşılaştırmanın sonuçlarını bir skalerle karşılaştırırken ve atarken cmp ve <=> da kullanabilirsiniz. $ var = $ var1 cmp $ var2; 'cmp' ve '<=>' (sayısal karşılaştırmalar için kullanılır), sol bağımsız değişken sağ bağımsız değişkenten küçük, eşit veya daha büyükse -1, 0 veya 1 değerini döndürür. Boolean değil ama bazen bir argümanın sadece eşit veya eşit değil, diğerine eşit veya daha büyük olup olmadığını bilmek isteyebilirsiniz.
user118435

9
Sorun 1: Boş bir liste yanlış değildir, çünkü bir listenin doğru veya yanlış olup olmadığını kontrol etmek imkansızdır. Skaler bağlamda boş bir liste geri döner undef.
ikegami

4
Problem 2: ('')ve ''aynı değerlerdir. Sanırım boş bir dizeden oluşan bir öğe içeren bir liste ima etmek istediniz (parensler liste oluşturmasa bile), ancak daha önce de belirttiğim gibi, bir listenin yanlış olup olmadığını kontrol etmek imkansız.
ikegami

6
Sorun 3: Aşırı boolean işlecine sahip nesneler de yanlış olabilir.
ikegami

15
@eternicode, Perl, doğru ve yanlış döndürmesi gerektiğinde kullandığı iki özel değere sahiptir, bu yüzden sadece booleans içermez, doğru ( !0aka PL_sv_yes) ve yanlış ( !1aka PL_sv_no) vardır. Yoksa Perl'in bu iki değerden başka bir şey doğruluk açısından test edildiğinde sarılması gerektiğini mi söylüyorsunuz? Bu tamamen korkunç olurdu. Örneğin önleyecektir$x ||= $default;
ikegami

71

Karşılaştığım yanlışlığın en eksiksiz ve özlü tanımı:

Boş dizeye veya dizeye dizgi oluşturan 0her şey yanlıştır. Diğer her şey doğrudur.

Bu nedenle, aşağıdaki değerler yanlıştır:

  • Boş dize
  • Sayısal değer sıfır
  • Tanımlanmamış bir değer
  • Yukarıdakilerden birini değerlendiren aşırı yüklenmiş bir boole işleçine sahip bir nesne.
  • Getirme sırasında yukarıdakilerden birini değerlendiren büyülü bir değişken.

Boş bir liste değişmezinin skaler bağlamda tanımlanmamış bir değeri değerlendirdiğini, dolayısıyla yanlış bir şeyi değerlendirdiğini unutmayın.


"Gerçek sıfırlar" üzerine bir not

0Dize olarak nitelenen sayılar yanlış olsa da, sıfıra kadar olan dizeler zorunlu değildir. Yalnızca yanlış dizeler 0ve boş dize vardır. Başka herhangi bir dize, sıfıra doğru olsa bile doğrudur.

Aşağıda, bir boole olarak doğru ve sayı olarak sıfır olan dizeler verilmiştir:

  • Uyarı yapmadan:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Bir uyarı ile:
    • Scalar::Util::looks_like_numberFalse değerini döndüren herhangi bir dize . (ör. "abc")

Birazdan sözcüğü seni anladım eğer doğruysa içinde 0'a stringify sayılar doğruysa iken olmalıdır sahte ya da (karışıklığı önlemek için) yanlış olarak değerlendirmek .
Dmitry Korolyov

1
"Özlü" tanımınız daha uzun açıklamanızla tutarsız. Düşünün: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Şimdi $value"XXX" şeklinde dizgi yapacak, ancak false değerine yükseltilecek.
tobyink

1
@tobyink, Kısa versiyon mükemmel değil, sadece bulduğum en iyisi. Her şeyi kapsayan değil pratik olması gerekiyordu. Tarafından döndürülen değerin booldizgi haline geldiğini unutmayın 0. Ayrıca, tutarsız aşırı yükler oluşturmaktan vazgeçersiniz ve geri döndüğünüz değerler böyle düşünülebilir. (örneğin a &&, a olarak optimize edilebilir ||, bu nedenle bunlar tutarsız olsaydı, bir sorununuz olurdu.)
ikegami

0x00Burada ele alınıp alınmadığından emin değilim .
Zaid

@Zaid, Kod 0x00(sıfır sayısal değeri) veya dize 0x00(bunun looks_like_numberiçin yanlış olan) tarafından döndürülen değeri mi kastediyorsunuz ? Her iki durumda da, zaten kaplıdır.
ikegami

59

Perl yerel bir boolean tipine sahip değildir, ancak aynı davranışı elde etmek için tamsayıların veya dizelerin karşılaştırmasını kullanabilirsiniz. Alan'ın örneği, tamsayıların karşılaştırmasını kullanarak bunu yapmanın güzel bir yoludur. İşte bir örnek

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

Bazı programlarımda yaptığım bir şey, bir sabit kullanarak aynı davranışı eklenir:

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

"Use constant" ile işaretlenen satırlar, her zaman 1 olarak değerlendirilen true adında bir sabit ve her zaman 0 ile değerlendirilen false adında bir sabit tanımlar. Perl'de sabitlerin tanımlanma biçimi nedeniyle, aşağıdaki kod satırları da başarısız olur:

true = 0;
true = false;

Hata iletisi, "Skaler atamada sabit değiştirilemiyor" gibi bir şey söylemelidir.

Bunu dizelerden karşılaştırmayı sorduğunuz yorumlardan birinde gördüm. Bilmelisiniz ki Perl, dizeleri ve sayısal türleri skaler değişkenlerde birleştirdiğinden, dizeleri ve sayıları karşılaştırmak için farklı sözdizimine sahipsiniz:

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

Bu operatörler arasındaki fark Perl'de çok yaygın bir karışıklık kaynağıdır.


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

11
Sabitleri fakir olarak kullanmak makroları bu şekilde tehlikelidir. Bu kod örnekleri eşdeğer değildir: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, sıradan bir gözlemci için açık olmayabilir. (Ve evet, son örnek zayıf programlama stilidir, ancak bu konunun yanındadır).
Zano

16

Ben tavsiye ederim use boolean;. Boolean modülünü cpan'dan kurmanız gerekiyor .


7
Perl'de, hayatta olduğu gibi, birçok gerçek var. Deneyimsiz gibi aptalca şeyler yazmak gibi if ($my_true_value == true). Benim deneyime göre, acıya giden yol ve verimsiz kod, Bir Gerçek Hakikat olduğunu iddia etmek.
tjd

2
Perl doğaya göre felsefi
ILMostro_7

13

Favorilerim her zaman oldu

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

iç temsilden tamamen bağımsız olan


5
Parlak. Perl programlama dilini tek elle sabitlediniz!
Nostalg.io

8

Perl'de hangi değerlerin doğru ve yanlış olduğu hakkında iyi bir açıklamaya sahip bir öğretici ile karşılaştım . Şunu belirtir:

Aşağıdaki skaler değerler yanlış kabul edilir:

  • undef - tanımlanmamış değer
  • 0 000 veya 0.0 olarak yazsanız bile 0 sayısı
  • '' boş dize.
  • '0' tek bir 0 rakamı içeren dize.

Aşağıdakiler dahil olmak üzere diğer tüm skaler değerler doğrudur:

  • 1 0 olmayan herhangi bir sayı
  • ' ' içinde boşluk olan dize
  • '00' bir dizede iki veya daha fazla 0 karakter
  • "0\n" a 0 ve ardından yeni satır
  • 'true'
  • 'false' evet, 'false' dizesi bile doğru olarak değerlendirilir.

Perl hakkında doğru ve yanlış açıklayan iyi bir öğretici daha var .


6

Bobf tarafından Boole değerleri için verilen güzel açıklama : Doğru mu Yanlış mı? Hızlı Başvuru Kılavuzu

Farklı değerler için doğruluk testleri

                       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

Kötü cevap, ama perlmonks.org güçlü, saygın bir kaynak. Yorum ve bağlantı yerine gerçek içeriğe sahip olmak güzel olurdu . : - /
ILMostro_7

0

Aşağıdaki dosya önekini kullanın, bu perl betiğinize eTRUE ve eFALSE ekleyecektir, aslında GERÇEK (!) doğru ve yanlış olacaktır (tıpkı java gibi)

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

Aslında bunu kullanmanız için birkaç neden var.

Benim nedenim JSON ile çalışmak, anahtarlara değer olarak 0 ve 1 var, ama bu kesmek komutunuz boyunca doğru değerlerin korunmasını sağlayacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.