【问题标题】:How do I use boolean variables in Perl?如何在 Perl 中使用布尔变量?
【发布时间】:2010-11-05 09:36:18
【问题描述】:

我试过了:

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

这些都不起作用。我收到错误消息

使用“strict subs”时不允许使用裸词“false”。

【问题讨论】:

  • 你可能想从我的书Learning Perl开始。这比在你做对之前猜测要做什么要容易(猴子、打字机和哈姆雷特等等)。 :)

标签: perl boolean


【解决方案1】:

在 Perl 中,以下条件的计算结果为 false:

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

其余的都是真的。 truefalse 没有裸词。

【讨论】:

  • @BlueWaldo:在比较并将比较结果分配给标量时,您还可以使用 cmp 和 。 $var = $var1 cmp $var2; 'cmp' 和 ''(用于数值比较)如果左参数小于、等于或大于右参数,则返回 -1、0 或 1。它不是布尔值,但有时您可能想知道一个参数是否等于或小于或大于另一个参数,而不是等于或不等于。
  • 问题1:空列表不是假的,因为无法检查列表是真还是假。标量上下文中的空列表返回 undef
  • 问题 2:('')'' 是相同的值。我想你想暗示一个包含一个空字符串的元素的列表(即使括号不创建列表),但正如我已经提到的,不可能检查一个列表是真还是假。跨度>
  • 问题3:带有重载布尔运算符的对象也可以为假。
  • @eternicode,Perl 在需要返回 true 和 false 时确实有两个特定的值,所以它不仅有布尔值,它还有 true (!0 aka PL_sv_yes) 和 false (!1 又名PL_sv_no)。或者你是说 Perl 应该在测试这两个值以外的东西的真实性时发出嘶嘶声?那将是完全可怕的。例如它会阻止$x ||= $default;
【解决方案2】:

我遇到的最完整、最简洁的 false 定义是:

任何字符串化为空字符串或字符串0 的都是假的。其他都是真的。

因此,以下值为假:

  • 空字符串
  • 数值为零
  • 一个未定义的值
  • 一个具有重载布尔运算符的对象,该运算符对上述之一进行求值。
  • 一个神奇的变量,在提取时计算为上述之一。

请记住,空列表文字在标量上下文中的计算结果为未定义值,因此它的计算结果为 false。


关于“真零”的说明

虽然字符串化为 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"

【讨论】:

  • 如果我理解正确的话,字符串化为 0 的数字为真 中的 true 应该是 false 或(防止混淆)评估为假
  • 您的“简洁”定义与您较长的解释不一致。考虑:my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };。现在$value 将字符串化为“XXX”,但布尔化为 false。
  • @tobyink,简洁的版本并不完美,只是我找到的最好的版本。它应该是实用的,而不是包罗万象的。请注意,bool 返回的值会字符串化为0。此外,不鼓励您创建不一致的重载,并且您返回的值可能被视为此类。 (例如,&& 可以优化为 ||,因此如果这些不一致,您就会遇到问题。)
  • 我不确定这里是否涵盖0x00
  • @Zaid,您是指代码0x00(数值为零)还是字符串0x00(其中looks_like_number 为假)返回的值?不管怎样,它已经被覆盖了。
【解决方案3】:

Perl 没有本机布尔类型,但您可以使用整数或字符串的比较来获得相同的行为。 Alan 的示例是使用整数比较的一种很好的方法。这是一个例子

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

在“使用常量”中标记的行定义了一个名为 true 的常量,它总是计算为 1,一个名为 false 的常量总是计算为 0。由于 Perl 中定义常量的方式,以下代码行失败还有:

true = 0;
true = false;

错误消息应该显示类似“无法修改标量赋值中的常量”。

我在您询问的有关比较字符串的一个 cmets 中看到了这一点。你应该知道,因为 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 中非常常见的混淆来源。

【讨论】:

  • use warnings; 而不是 #! perl -w
  • 以这种方式将常量用作穷人的宏是危险的。这些代码示例并不相同:if ($exitstatus) { exit; }if ($exitstatus == true) { exit; },这对于普通的观察者来说可能并不明显。 (是的,最后一个例子是糟糕的编程风格,但这不是重点)。
【解决方案4】:

我推荐use boolean;。你必须从 cpan 安装 boolean 模块。

【讨论】:

  • 在 Perl 中,就像在生活中一样,有许多真理。没有经验的人喜欢写if ($my_true_value == true)之类的傻事。以我的经验,假装有一个真实的真理是一条通往痛苦和低效代码的道路。
  • Perl 本质上是哲学的
【解决方案5】:

我的最爱一直是

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

完全独立于内部表示。

【讨论】:

  • 太棒了。你单枪匹马地修复了 Perl 编程语言!
【解决方案6】:

我遇到了一个tutorial,它很好地解释了Perl 中哪些值是真假。它指出:

以下标量值被认为是错误的:

  • undef - 未定义的值
  • 0 数字 0,即使你写成 000 或 0.0
  • '' 空字符串。
  • '0' 包含单个 0 数字的字符串。

所有其他标量值,包括以下为真:

  • 1 任意非0数
  • ' ' 里面有空格的字符串
  • '00'一个字符串中有两个或多个0字符
  • "0\n" 0 后跟换行符
  • 'true'
  • 'false' 是的,即使字符串 'false' 的计算结果为 true。

还有另一个很好的教程解释了Perl true and false

【讨论】:

    【解决方案7】:

    bobf 对布尔值给出了很好的解释:True or False? A Quick Reference Guide

    不同值的真值测试

                           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 中是一个强大的、有信誉的来源。最好有一些真实的内容,而不是评论和链接。 :-/
    【解决方案8】:

    使用以下文件前缀,这将添加到您的 perl 脚本 eTRUE 和 eFALSE,它实际上是 REAL(!) true 和 false(就像 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' )
                 };
    

    实际上,您应该使用它的原因很少。

    我的原因是使用 JSON,我有 0 和 1 作为键的值,但是这个 hack 将确保在您的脚本中保留正确的值。

    【讨论】:

      【解决方案9】:

      Raku(以前称为 Perl_6 的编程语言)中的布尔值:

      ~$ raku
      Welcome to ??????™ v2021.06.
      Implementing the ????™ programming language v6.d.
      Built on MoarVM version 2021.06.
      
      To exit type 'exit' or '^D'
      
      > my $var = False;
      False
      > say $var;
      False
      
      > say $var.^name
      Bool
      > say $var.WHAT
      (Bool)
      
      > say ++$var
      True
      > say --$var
      False
      
      > say $var.Int
      0
      > say $var.Int + 1
      1
      > say ($var.Int + 1).Bool
      True
      > say $var.Int - 1
      -1
      > say ($var.Int - 1).Bool
      True
      
      > say $var.succ
      True
      > say $var.Int.succ
      1
      > say $var.pred
      False
      > say $var.Int.pred
      -1
      
      > say ++($var.Int); #ERROR
      Cannot resolve caller prefix:<++>(Int:D); the following candidates
      match the type but require mutable arguments:
          (Mu:D $a is rw)
          (Int:D $a is rw --> Int:D)
          #<SNIP>    
      > say --($var.Int); #ERROR
      Cannot resolve caller prefix:<-->(Int:D); the following candidates
      match the type but require mutable arguments:
          (Mu:D $a is rw)
          (Int:D $a is rw --> Int:D)
          #<SNIP>
      
      > exit
      

      https://docs.raku.org/type/Bool
      https://docs.raku.org/language/syntax#index-entry-Boolean_(literals)

      【讨论】:

        猜你喜欢
        • 2012-09-27
        • 1970-01-01
        • 2021-12-11
        • 2013-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-21
        相关资源
        最近更新 更多