Bagaimana cara menggunakan variabel boolean di Perl?

220

Saya telah mencoba:

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

Tak satu pun dari ini bekerja. Saya mendapatkan pesan kesalahan

Bareword "false" tidak diizinkan saat "subs ketat" sedang digunakan.
Chad DeShon
sumber
37
Anda mungkin ingin memulai dengan buku saya Learning Perl . Lebih mudah daripada menebak apa yang harus dilakukan sampai Anda melakukannya dengan benar (monyet, mesin tik, dan Hamlet, dan semua itu). :)
brian d foy

Jawaban:

285

Dalam Perl, yang berikut ini bernilai false dalam kondisi:

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

Sisanya benar. Tidak ada kata kunci untuk trueatau false.

Alan Haggai Alavi
sumber
2
@BlueWaldo: Anda juga dapat menggunakan cmp dan <=> saat membandingkan dan menetapkan hasil perbandingan ke skalar. $ var = $ var1 cmp $ var2; 'cmp' dan '<=>' (digunakan untuk perbandingan numerik) mengembalikan -1, 0, atau 1 jika argumen kiri kurang dari, sama dengan, atau lebih besar dari argumen kanan. Ini bukan boolean tetapi kadang-kadang Anda mungkin ingin tahu apakah satu argumen ir sama atau kurang dari atau lebih besar dari yang lain, bukan hanya sama atau tidak sama.
user118435
9
Masalah 1: Daftar kosong tidak salah, karena tidak mungkin untuk memeriksa apakah daftar itu benar atau salah. Daftar kosong dalam konteks skalar kembali undef.
ikegami
4
Masalah 2: ('')dan ''nilainya sama. Saya pikir Anda ingin menyiratkan daftar dengan elemen yang terdiri dari string kosong (walaupun parens tidak membuat daftar), tetapi seperti yang telah saya sebutkan, tidak mungkin untuk memeriksa apakah daftar itu benar atau salah.
ikegami
6
Masalah 3: Objek dengan operator boolean yang kelebihan beban juga bisa salah.
ikegami
15
@eternicode, Perl memang memiliki dua nilai spesifik yang digunakan ketika perlu mengembalikan benar dan salah, jadi tidak hanya memiliki boolean, ia memiliki true ( !0alias PL_sv_yes) dan false ( !1aka PL_sv_no). Atau apakah Anda mengatakan Perl seharusnya tidak berubah setiap kali sesuatu selain kedua nilai ini diuji kebenarannya? Itu akan sangat mengerikan. misalnya itu akan mencegah$x ||= $default;
ikegami
71

Definisi palsu paling lengkap dan ringkas yang pernah saya temui adalah:

Apa pun yang merangkai ke string kosong atau string 0itu salah. Yang lainnya benar.

Oleh karena itu, nilai-nilai berikut ini salah:

  • String kosong
  • Nilai numerik nol
  • Nilai yang tidak ditentukan
  • Objek dengan operator boolean yang kelebihan beban yang mengevaluasi salah satu di atas.
  • Variabel ajaib yang mengevaluasi salah satu di atas saat mengambil.

Perlu diingat bahwa daftar literal kosong mengevaluasi ke nilai yang tidak ditentukan dalam konteks skalar, jadi itu mengevaluasi ke sesuatu yang salah.


Catatan tentang "nol sejati"

Meskipun angka yang dirujuk 0salah, string yang numify ke nol belum tentu. Satu-satunya string palsu adalah 0dan string kosong. String lain, bahkan jika numify menjadi nol, adalah benar.

Berikut ini adalah string yang benar sebagai boolean dan nol sebagai angka:

  • Tanpa peringatan:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Dengan peringatan:
    • String apa pun yang Scalar::Util::looks_like_numbermengembalikan false. (mis. "abc")
ikegami
sumber
jika saya mengerti Anda benar kata true di While angka-angka yang merangkai ke 0 benar harus salah atau (untuk mencegah kebingungan) mengevaluasi ke false .
user907860
1
Definisi "ringkas" Anda tidak konsisten dengan penjelasan yang lebih panjang. Pertimbangkan: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Sekarang $valueakan dikencangkan menjadi "XXX" tetapi boolify menjadi false.
tobyink
1
@tobyink, Versi ringkasnya tidak sempurna, hanya yang terbaik yang saya temukan. Ini dimaksudkan untuk menjadi praktis, tidak mencakup semua. Perhatikan bahwa nilai yang dikembalikan oleh boolstring Anda menjadi 0. Selain itu, Anda tidak disarankan untuk membuat overload yang tidak konsisten, dan nilai yang Anda kembalikan dapat dianggap demikian. (mis. a &&dapat dioptimalkan menjadi ||, jadi jika ini tidak konsisten, Anda akan memiliki masalah.)
ikegami
Saya tidak yakin apakah 0x00dibahas di sini.
Zaid
@Zaid, Apakah maksud Anda nilai yang dikembalikan oleh kode 0x00(nilai numerik nol) atau string 0x00(yang looks_like_numbersalah)? Either way, itu sudah dibahas.
ikegami
59

Perl tidak memiliki tipe boolean asli, tetapi Anda dapat menggunakan perbandingan bilangan bulat atau string untuk mendapatkan perilaku yang sama. Contoh Alan adalah cara yang baik untuk melakukannya dengan menggunakan perbandingan bilangan bulat. Ini sebuah contoh

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

Satu hal yang saya lakukan di beberapa program saya adalah menambahkan perilaku yang sama menggunakan konstanta:

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

Baris yang ditandai dalam "use constant" mendefinisikan konstanta bernama true yang selalu mengevaluasi ke 1, dan konstanta bernama false yang selalu dievaluasi oleh 0. Karena cara konstanta didefinisikan dalam Perl, baris kode berikut juga gagal:

true = 0;
true = false;

Pesan kesalahan harus mengatakan sesuatu seperti "Tidak dapat mengubah konstan dalam tugas skalar."

Saya melihat bahwa di salah satu komentar Anda bertanya tentang membandingkan string. Anda harus tahu bahwa karena Perl menggabungkan string dan tipe numerik dalam variabel skalar, Anda memiliki sintaks berbeda untuk membandingkan string dan angka:

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

Perbedaan antara operator ini adalah sumber kebingungan yang sangat umum di Perl.

James Thompson
sumber
5
use warnings;bukannya#! perl -w
Brad Gilbert
11
Menggunakan konstanta sebagai makro pria miskin dengan cara itu berbahaya. Contoh kode ini tidak setara: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, yang mungkin tidak jelas bagi pengamat biasa. (Dan ya, contoh terakhir adalah gaya pemrograman yang buruk, tapi itu intinya).
Zano
16

Saya merekomendasikan use boolean;. Anda harus menginstal modul boolean dari cpan.

xenoterracide
sumber
7
Dalam Perl, seperti dalam kehidupan, ada banyak kebenaran. Orang yang tidak berpengalaman suka menulis hal-hal konyol seperti if ($my_true_value == true). Berpura-pura bahwa ada Satu Kebenaran Sejati, dalam pengalaman saya, jalan menuju rasa sakit, dan kode yang tidak efisien.
tjd
2
Perl bersifat filosofis
ILMostro_7
13

Favorit saya selalu begitu

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

yang sepenuhnya independen dari representasi internal.

syck
sumber
5
Cemerlang. Anda sendirian memperbaiki bahasa pemrograman Perl!
Nostalg.io
8

Saya menemukan tutorial yang memiliki penjelasan yang baik tentang Nilai-nilai apa yang benar dan salah di Perl . Ini menyatakan bahwa:

Nilai skalar berikut ini dianggap salah:

  • undef - nilai yang tidak ditentukan
  • 0 angka 0, bahkan jika Anda menuliskannya sebagai 000 atau 0,0
  • '' string kosong.
  • '0' string yang berisi 0 digit tunggal.

Semua nilai skalar lainnya, termasuk yang berikut ini benar:

  • 1 nomor bukan-0
  • ' ' string dengan spasi di dalamnya
  • '00' dua atau lebih 0 karakter dalam sebuah string
  • "0\n" a 0 diikuti oleh baris baru
  • 'true'
  • 'false' ya, bahkan string 'false' dinilai benar.

Ada tutorial bagus lainnya yang menjelaskan tentang Perl benar dan salah .

serenesat
sumber
6

Penjelasan indah yang diberikan oleh bobf untuk nilai Boolean: Benar atau Salah? Panduan Referensi Cepat

Tes kebenaran untuk nilai yang berbeda

                       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
sumber
Jawaban yang buruk, tetapi sumber yang kuat dan memiliki reputasi baik di perlmonks.org. Alangkah baiknya memiliki beberapa konten nyata, bukan komentar dan tautan. : - /
ILMostro_7
0

gunakan awalan file berikut, ini akan menambah skrip perl Anda eTRUE dan eFALSE, itu sebenarnya akan REAL (!) benar dan salah (seperti 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' )
             };

Sebenarnya, ada beberapa alasan mengapa Anda harus menggunakannya.

Alasan saya adalah bahwa bekerja dengan JSON, saya punya 0 dan 1 sebagai nilai untuk kunci, tetapi peretasan ini akan memastikan nilai yang benar disimpan di sepanjang skrip Anda.


sumber