Làm cách nào để sử dụng biến boolean trong Perl?


220

Tôi đã thử:

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

Không ai trong số này làm việc. Tôi nhận được thông báo lỗi

Bareword "sai" không được phép trong khi "phụ nghiêm ngặt" đang được sử dụng.

37
Bạn có thể muốn bắt đầu với cuốn sách Học Perl của tôi . Nó dễ hơn là đoán những việc cần làm cho đến khi bạn hiểu đúng (khỉ, máy đánh chữ và Hamlet, và tất cả những thứ đó). :)
brian d foy

Câu trả lời:


285

Trong Perl, các đánh giá sau đây là sai trong các điều kiện:

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

Phần còn lại là đúng. Không có barewords cho truehoặc false.


2
@BlueWaldo: bạn cũng có thể sử dụng cmp và <=> khi so sánh và gán kết quả so sánh với vô hướng. $ var = $ var1 cmp $ var2; 'cmp' và '<=>' (được sử dụng để so sánh số) trả về -1, 0 hoặc 1 nếu đối số bên trái nhỏ hơn, bằng hoặc lớn hơn đối số bên phải. Nó không phải là boolean nhưng đôi khi bạn có thể muốn biết nếu một đối số ir bằng hoặc nhỏ hơn hoặc lớn hơn đối số khác thay vì chỉ bằng hoặc không bằng.
dùng118435

9
Vấn đề 1: Danh sách trống không sai, vì không thể kiểm tra xem danh sách đó là đúng hay sai. Một danh sách trống trong bối cảnh vô hướng trả về undef.
ikegami

4
Bài toán 2: ('')''có cùng giá trị. Tôi nghĩ rằng bạn muốn ám chỉ một danh sách với một thành phần bao gồm một chuỗi rỗng (mặc dù parens không tạo danh sách), nhưng như tôi đã đề cập, không thể kiểm tra xem danh sách đó có đúng không.
ikegami

6
Bài toán 3: Các đối tượng có toán tử boolean quá tải cũng có thể sai.
ikegami

15
@eternicode, Perl có hai giá trị cụ thể mà nó sử dụng khi cần trả về true và false, vì vậy nó không chỉ có booleans, mà còn có true ( !0aka PL_sv_yes) và false ( !1aka PL_sv_no). Hay bạn đang nói Perl nên uốn éo bất cứ khi nào một cái gì đó ngoài hai giá trị này được kiểm tra tính trung thực? Điều đó sẽ hoàn toàn khủng khiếp. ví dụ: Nó sẽ ngăn chặn$x ||= $default;
ikegami

71

Định nghĩa ngắn gọn, đầy đủ nhất về sai mà tôi đã gặp là:

Bất cứ điều gì xâu chuỗi thành chuỗi rỗng hoặc chuỗi 0là sai. Mọi thứ khác đều đúng.

Do đó, các giá trị sau là sai:

  • Chuỗi rỗng
  • Giá trị số bằng không
  • Một giá trị không xác định
  • Một đối tượng với một toán tử boolean quá tải để đánh giá một trong những điều trên.
  • Một biến số ma thuật đánh giá một trong những điều trên khi tìm nạp.

Hãy nhớ rằng một danh sách trống theo nghĩa đen sẽ đánh giá một giá trị không xác định trong ngữ cảnh vô hướng, vì vậy nó đánh giá thành một cái gì đó sai.


Một ghi chú về "số không thực"

Trong khi các số 0được xâu chuỗi thành sai, các chuỗi số hóa thành 0 không nhất thiết phải có. Các chuỗi sai duy nhất là 0và chuỗi trống. Bất kỳ chuỗi nào khác, ngay cả khi nó số hóa thành 0, là đúng.

Sau đây là các chuỗi đúng như boolean và 0 dưới dạng số:

  • Không có cảnh báo:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Với một cảnh báo:
    • Bất kỳ chuỗi nào Scalar::Util::looks_like_numbertrả về false. (ví dụ "abc")

nếu tôi hiểu bạn đúng từ đúng trong khi các số xâu thành 0 là đúng nên sai hoặc (để tránh nhầm lẫn) đánh giá thành sai .
dùng907860

1
Định nghĩa "súc tích" của bạn không phù hợp với lời giải thích dài hơn của bạn. Hãy xem xét : my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Bây giờ $valuesẽ xâu chuỗi thành "XXX" nhưng boolify thành false.
tobyink

1
@tobyink, Phiên bản súc tích không hoàn hảo, chỉ đơn thuần là phiên bản tốt nhất tôi tìm thấy. Nó có nghĩa là thiết thực, không bao gồm tất cả. Hãy lưu ý rằng giá trị được trả về bởi boolchuỗi của bạn 0. Ngoài ra, bạn không được khuyến khích tạo ra tình trạng quá tải không nhất quán và các giá trị bạn trả về có thể được coi là như vậy. (ví dụ: a &&có thể được tối ưu hóa thành a ||, vì vậy nếu những điều này không nhất quán, bạn sẽ gặp vấn đề.)
ikegami

Tôi không chắc chắn nếu 0x00được bảo hiểm ở đây.
Zaid

@Zaid, bạn có nghĩa là giá trị được trả về bởi mã 0x00(giá trị số 0) hoặc chuỗi 0x00(cho đó looks_like_numberlà sai)? Dù bằng cách nào, nó đã được bảo hiểm.
ikegami

59

Perl không có kiểu boolean riêng, nhưng bạn có thể sử dụng so sánh các số nguyên hoặc chuỗi để có cùng hành vi. Ví dụ của Alan là một cách hay để làm điều đó bằng cách sử dụng so sánh các số nguyên. Đây là một ví dụ

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

Một điều mà tôi đã thực hiện trong một số chương trình của mình được thêm vào cùng một hành vi bằng cách sử dụng hằng số:

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

Các dòng được đánh dấu trong "hằng số sử dụng" xác định hằng số có tên true luôn luôn ước tính là 1 và hằng số có tên false luôn luôn đánh giá bằng 0. Do cách các hằng số được định nghĩa trong Perl, các dòng mã sau cũng thất bại:

true = 0;
true = false;

Thông báo lỗi sẽ có nội dung như "Không thể sửa đổi hằng số trong gán vô hướng."

Tôi thấy rằng trong một trong những ý kiến ​​bạn hỏi về việc so sánh các chuỗi. Bạn nên biết rằng vì Perl kết hợp các chuỗi và kiểu số trong các biến vô hướng, nên bạn có cú pháp khác nhau để so sánh các chuỗi và số:

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

Sự khác biệt giữa các toán tử này là một nguồn gây nhầm lẫn rất phổ biến trong Perl.


5
use warnings;thay vì#! perl -w
Brad Gilbert

11
Sử dụng hằng số như một macro người nghèo theo cách đó rất nguy hiểm. Các ví dụ mã này không tương đương: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, có thể không rõ ràng đối với người quan sát thông thường. (Và vâng, ví dụ cuối cùng là phong cách lập trình kém, nhưng đó là vấn đề bên cạnh).
Zano

16

Tôi đề nghị use boolean;. Bạn phải cài đặt mô-đun boolean từ cpan.


7
Ở Perl, cũng như trong cuộc sống, có rất nhiều sự thật. Những người thiếu kinh nghiệm thích viết những thứ ngớ ngẩn như thế if ($my_true_value == true). Giả vờ rằng có một Sự thật là, theo kinh nghiệm của tôi, một con đường dẫn đến nỗi đau và mã không hiệu quả.
tjd

2
Perl là triết học tự nhiên
ILMostro_7

13

Yêu thích của tôi luôn luôn là

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

đó là hoàn toàn độc lập với các đại diện nội bộ.


5
Xuất sắc. Bạn tự tay sửa ngôn ngữ lập trình Perl!
Nỗi nhớ.io

8

Tôi đã xem qua một hướng dẫn có giải thích rõ về giá trị nào là đúng và sai trong Perl . Nó nói rằng:

Các giá trị vô hướng sau được coi là sai:

  • undef - giá trị không xác định
  • 0 số 0, ngay cả khi bạn viết nó là 000 hoặc 0,0
  • '' chuỗi rỗng.
  • '0' chuỗi chứa một chữ số 0 duy nhất.

Tất cả các giá trị vô hướng khác, bao gồm các giá trị sau là đúng:

  • 1 bất kỳ số nào không 0
  • ' ' chuỗi có khoảng trắng trong đó
  • '00' hai hoặc nhiều 0 ký tự trong một chuỗi
  • "0\n" 0 theo sau là một dòng mới
  • 'true'
  • 'false' có, ngay cả chuỗi 'false' cũng đánh giá là đúng.

Có một hướng dẫn tốt khác giải thích về Perl đúng và sai .


6

Giải thích tuyệt vời được đưa ra bởi bobf cho các giá trị Boolean: Đúng hay Sai? Hướng dẫn tham khảo nhanh

Kiểm tra sự thật cho các giá trị khác nhau

                       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

Câu trả lời kém, nhưng là một nguồn mạnh mẽ, có uy tín trong perlmonks.org. Sẽ thật tuyệt khi có một số nội dung thực sự thay vì một bình luận và một liên kết. : - /
ILMostro_7

0

sử dụng tiền tố tập tin sau, điều này sẽ thêm vào tập lệnh perl của bạn eTRUE và eFALSE, nó thực sự sẽ là REAL (!) đúng và sai (giống như 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' )
             };

Thực tế, có vài lý do tại sao bạn nên sử dụng nó.

Lý do của tôi là khi làm việc với JSON, tôi đã nhận 0 và 1 làm giá trị cho các khóa, nhưng bản hack này sẽ đảm bảo các giá trị chính xác được giữ theo tập lệnh của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.