ฉันจะใช้ตัวแปรบูลีนใน Perl ได้อย่างไร


220

ฉันเหนื่อย:

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

ไม่มีงานเหล่านี้ ฉันได้รับข้อความแสดงข้อผิดพลาด

Bareword "false" ไม่ได้รับอนุญาตในขณะที่ใช้ "subs subs" อย่างเข้มงวด

37
คุณอาจต้องการที่จะเริ่มต้นด้วยการอ่านหนังสือของฉันเรียนรู้ Perl มันง่ายกว่าการเดาว่าจะทำอะไรจนกว่าคุณจะทำถูกต้อง (ลิงเครื่องพิมพ์ดีดและแฮมเล็ตและสิ่งอื่น ๆ ) :)
brian d foy

คำตอบ:


285

ใน Perl การประเมินต่อไปนี้เป็นเท็จใน conditionals:

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

ส่วนที่เหลือเป็นเรื่องจริง ไม่มี barewords มีการหรือtruefalse


2
@BlueWaldo: คุณสามารถใช้ cmp และ <=> เมื่อเปรียบเทียบและกำหนดผลลัพธ์ของการเปรียบเทียบกับสเกลาร์ $ var = $ var1 cmp $ var2; 'cmp' และ '<=>' (ใช้สำหรับการเปรียบเทียบตัวเลข) ส่งคืน -1, 0 หรือ 1 หากอาร์กิวเมนต์ซ้ายน้อยกว่าเท่ากับหรือมากกว่าอาร์กิวเมนต์ที่ถูกต้อง ไม่ใช่บูลีน แต่บางครั้งคุณอาจต้องการที่จะรู้ว่าอาร์กิวเมนต์หนึ่งมีค่าเท่ากับหรือน้อยกว่าหรือมากกว่าค่าอื่นแทนแทนที่จะเท่ากับหรือไม่เท่ากัน
user118435

9
ปัญหา 1: รายการว่างเปล่าไม่ใช่เท็จเนื่องจากเป็นไปไม่ได้ที่จะตรวจสอบว่ารายการนั้นเป็นจริงหรือเท็จ undefรายการที่ว่างเปล่าในผลตอบแทนบริบทเกลา
ikegami

4
ปัญหาที่ 2: ('')และ''เป็นค่าเดียวกัน ฉันคิดว่าคุณต้องการแสดงรายการด้วยองค์ประกอบที่ประกอบด้วยสตริงว่าง (แม้ว่า parens ไม่สร้างรายการ) แต่อย่างที่ฉันได้กล่าวไปแล้วมันเป็นไปไม่ได้ที่จะตรวจสอบว่ารายการนั้นเป็นเท็จหรือไม่
ikegami

6
ปัญหาที่ 3: วัตถุที่มีตัวดำเนินการบูลีนที่โอเวอร์โหลดอาจเป็นเท็จได้เช่นกัน
ikegami

15
@eternicode, Perl มีค่าสองค่าที่ใช้เมื่อต้องการส่งกลับค่าจริงและเท็จดังนั้นจึงไม่เพียง แต่มีบูลีนเท่านั้น แต่ยังมีค่าจริง ( !0aka PL_sv_yes) และเท็จ ( !1aka PL_sv_no) หรือคุณกำลังพูดว่า Perl ควรบ่นเมื่อใดก็ตามที่มีค่าอื่นนอกเหนือจากสองค่านี้ถูกทดสอบเพื่อความจริง? นั่นจะน่ากลัวอย่างสมบูรณ์ เช่นมันจะป้องกัน$x ||= $default;
ikegami

71

คำจำกัดความที่สมบูรณ์และกระชับที่สุดของเท็จที่ฉันได้พบคือ:

อะไรก็ตามที่ทำให้เป็นสตริงว่างหรือสตริง0นั้นเป็นเท็จ ทุกสิ่งทุกอย่างเป็นเรื่องจริง

ดังนั้นค่าต่อไปนี้จึงเป็นเท็จ:

  • สตริงว่าง
  • ค่าตัวเลขศูนย์
  • ค่าที่ไม่ได้กำหนด
  • วัตถุที่มีตัวดำเนินการบูลีนโอเวอร์โหลดที่ประเมินค่าข้างต้นอย่างใดอย่างหนึ่ง
  • ตัวแปรเวทย์มนตร์ที่ประเมินหนึ่งในด้านบนในการดึงข้อมูล

โปรดทราบว่ารายการว่างตามตัวอักษรจะประเมินค่าที่ไม่ได้กำหนดในบริบทสเกลาร์ดังนั้นจึงประเมินสิ่งที่ผิดพลาด


หมายเหตุเกี่ยวกับ "ศูนย์จริง"

ในขณะที่ตัวเลขที่ทำให้0เป็นสตริงจะเป็นเท็จ แต่สตริงที่มีค่าเป็นศูนย์จะไม่จำเป็น สตริงเท็จเท่านั้น0และสตริงที่ว่างเปล่า สตริงอื่นใด ๆ แม้ว่าค่านั้นจะเป็นศูนย์จะเป็นจริงก็ตาม

ต่อไปนี้เป็นสตริงที่เป็นจริงเป็นบูลีนและเป็นศูนย์เป็นตัวเลข:

  • โดยไม่มีการเตือน:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • ด้วยคำเตือน:
    • สตริงใด ๆ ที่Scalar::Util::looks_like_numberส่งคืน false (เช่น"abc")

ถ้าผมเข้าใจคุณสิทธิคำที่แท้จริงในขณะที่ตัวเลขที่ stringify 0 เป็นจริงควรจะเป็นเท็จหรือ (เพื่อป้องกันการสับสน) ประเมินเป็นเท็จ
Dmitry Korolyov

1
คำจำกัดความ "รัดกุม" ของคุณไม่สอดคล้องกับคำอธิบายที่ยาวขึ้น พิจารณา: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. ตอนนี้$valueจะเปลี่ยนเป็น "XXX" แต่เปลี่ยนเป็นเท็จ
tobyink

1
@tobyink รุ่นสั้นกระชับไม่สมบูรณ์แบบที่สุดเท่าที่ฉันเคยพบมา มันหมายถึงการปฏิบัติไม่ใช่ทั้งหมดที่ครอบคลุม ทำบันทึกว่าค่าส่งกลับโดยคุณไม่ให้bool stringify 0นอกจากนี้คุณไม่ควรสร้างเกินพิกัดที่ไม่สอดคล้องกันและค่าที่คุณส่งคืนอาจถูกพิจารณาเช่นกัน (เช่น a &&สามารถปรับให้เหมาะกับ a ||ดังนั้นหากสิ่งเหล่านี้ไม่สอดคล้องกันคุณจะมีปัญหา)
ikegami

ฉันไม่แน่ใจว่า0x00ครอบคลุมอยู่ที่นี่หรือไม่
Zaid

@ Zaid คุณหมายถึงค่าที่ส่งคืนโดยรหัส0x00(ค่าตัวเลขศูนย์) หรือสตริง0x00(ซึ่งlooks_like_numberเป็นเท็จ) หรือไม่ ไม่ว่าจะด้วยวิธีใด
ikegami

59

Perl ไม่มีประเภทบูลีนดั้งเดิม แต่คุณสามารถใช้การเปรียบเทียบจำนวนเต็มหรือสตริงเพื่อให้ได้พฤติกรรมเดียวกัน ตัวอย่างของอลันเป็นวิธีที่ดีในการทำเช่นนั้นโดยใช้การเปรียบเทียบจำนวนเต็ม นี่คือตัวอย่าง

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

สิ่งหนึ่งที่ฉันได้ทำในบางโปรแกรมของฉันคือการเพิ่มพฤติกรรมเดียวกันโดยใช้ค่าคงที่:

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

บรรทัดที่ทำเครื่องหมายใน "ใช้ค่าคงที่" กำหนดค่าคงที่ชื่อจริงที่มักจะประเมินถึง 1 และค่าคงที่ชื่อเท็จที่ประเมินโดย 0 เสมอเนื่องจากวิธีการที่ค่าคงที่จะถูกกำหนดใน Perl บรรทัดรหัสต่อไปนี้จึงล้มเหลวเช่นกัน:

true = 0;
true = false;

ข้อความแสดงข้อผิดพลาดควรพูดว่า "ไม่สามารถแก้ไขค่าคงที่ในการกำหนดสเกลาร์"

ฉันเห็นว่าหนึ่งในความคิดเห็นที่คุณถามเกี่ยวกับการเปรียบเทียบสตริง คุณควรรู้ว่าเนื่องจาก Perl รวมสตริงและชนิดตัวเลขในตัวแปรสเกลาร์คุณมีไวยากรณ์ที่แตกต่างกันสำหรับการเปรียบเทียบสตริงและตัวเลข:

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

ความแตกต่างระหว่างผู้ประกอบการเหล่านี้เป็นแหล่งที่มาของความสับสนใน Perl


5
use warnings;แทน#! perl -w
แบรดกิลเบิร์ต

11
การใช้ค่าคงที่ในฐานะมาโครที่ยากจนนั้นเป็นอันตราย ตัวอย่างโค้ดเหล่านี้จะไม่เทียบเท่า: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }ซึ่งอาจไม่ชัดเจนสำหรับผู้สังเกตการณ์ทั่วไป (และใช่ตัวอย่างสุดท้ายคือรูปแบบการเขียนโปรแกรมที่ไม่ดี แต่อยู่ด้านข้างจุด)
Zano

16

use boolean;ผมขอแนะนำให้ คุณต้องติดตั้งโมดูลบูลีนจาก cpan แม้ว่า


7
ใน Perl เช่นเดียวกับในชีวิตมีความจริงมากมาย if ($my_true_value == true)มือใหม่เช่นการเขียนสิ่งที่โง่เหมือน ทำท่าว่ามีความจริงหนึ่งเดียวในประสบการณ์ของฉันเส้นทางสู่ความเจ็บปวดและรหัสที่ไม่มีประสิทธิภาพ
tjd

2
Perl เป็นปรัชญาโดยธรรมชาติ
ILMostro_7

13

รายการโปรดของฉันได้รับเสมอ

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

ซึ่งเป็นอิสระอย่างสมบูรณ์จากการเป็นตัวแทนภายใน


5
สุกใส คุณได้แก้ไขภาษาการเขียนโปรแกรม Perl เพียงลำพัง!
Nostalg.io

8

ผมมาในการกวดวิชาซึ่งมีคำอธิบายที่ดีเกี่ยวกับสิ่งที่มีค่าเป็นจริงและเท็จใน Perl มันระบุว่า:

ค่าสเกลาร์ต่อไปนี้ถือว่าเป็นเท็จ:

  • undef - ค่าที่ไม่ได้กำหนด
  • 0 หมายเลข 0 แม้ว่าคุณจะเขียนเป็น 000 หรือ 0.0
  • '' สตริงว่าง
  • '0' สตริงที่มี 0 หลักเดียว

ค่าสเกลาร์อื่น ๆ ทั้งหมดรวมถึงค่าต่อไปนี้เป็นจริง:

  • 1 หมายเลขที่ไม่ใช่ 0 ใด ๆ
  • ' ' สตริงที่มีช่องว่างในนั้น
  • '00' อักขระตั้งแต่สองตัวขึ้นไปในสตริง
  • "0\n" 0 ตามด้วยการขึ้นบรรทัดใหม่
  • 'true'
  • 'false' ใช่แม้กระทั่งสตริง 'false' ก็ให้ผลเป็นจริง

มีอีกกวดวิชาที่ดีที่อธิบายเกี่ยวกับการเป็นPerl จริงและเท็จ


6

คำอธิบายที่สวยงามโดยbobfสำหรับค่าบูลีน: จริงหรือเท็จ? คู่มืออ้างอิงด่วน

การทดสอบความจริงสำหรับค่าที่แตกต่าง

                       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

คำตอบไม่ดี แต่เป็นแหล่งที่แข็งแกร่งและมีชื่อเสียงใน perlmonks.org มันจะดีถ้ามีเนื้อหาจริงแทนที่จะแสดงความคิดเห็นและลิงค์ : - /
ILMostro_7

0

ใช้คำนำหน้าไฟล์ต่อไปนี้สิ่งนี้จะเพิ่มไปยังสคริปต์ perl ของคุณและ eFALSE มันจะเป็นจริง (!) จริงและเท็จ (เช่นเดียวกับจาวา)

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

จริงๆแล้วมีเหตุผลบางประการที่คุณควรใช้สิ่งนั้น

เหตุผลของฉันคือการทำงานกับ JSON ฉันมี 0 และ 1 เป็นค่าสำหรับคีย์ แต่แฮ็คนี้จะทำให้แน่ใจว่าค่าที่ถูกต้องจะถูกเก็บไว้ในสคริปต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.