【问题标题】:What do Perl functions that return Boolean actually return返回布尔值的 Perl 函数实际上返回什么
【发布时间】:2012-11-11 07:09:24
【问题描述】:

Perl defined 函数(以及许多其他函数)返回“布尔值”。

鉴于 Perl 实际上没有布尔类型(并且使用像 1 这样的值来表示 true,以及 0undef for false) Perl 语言是否准确指定布尔值返回的内容?例如,defined(undef) 会返回 0 还是 undef,是否会发生变化?

【问题讨论】:

  • 旁注:您可以使用双重否定将任何值转换为其对应的布尔值。这导致!! 伪运算符。对于返回通用的真值或假值而不是一些幻数非常有用。

标签: perl boolean return


【解决方案1】:

在几乎所有情况下(即除非有理由不这样做),Perl 返回两个静态分配的标量之一:&PL_sv_yes(为真)和&PL_sv_no(为假)。这是他们的详细信息:

>perl -MDevel::Peek -e"Dump 1==1"
SV = PVNV(0x749be4) at 0x3180b8
  REFCNT = 2147483644
  FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
  IV = 1
  NV = 1
  PV = 0x742dfc "1"\0
  CUR = 1
  LEN = 12

>perl -MDevel::Peek -e"Dump 1==0"
SV = PVNV(0x7e9bcc) at 0x4980a8
  REFCNT = 2147483647
  FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x7e3f0c ""\0
  CUR = 0
  LEN = 12

yes 是一个三元组(IOK、NOK 和 POK)。它包含一个等于 1 的有符号整数 (IV)、一个等于 1 的浮点数 (NV) 和一个等于 1 的字符串 (PV)。

no 也是一个三元组(IOK、NOK 和 POK)。它包含一个等于 0 的有符号整数 (IV)、一个等于 0 的浮点数 (NV) 和一个空字符串 (PV)。这意味着它字符串化为空字符串,并且它被数字化为0。它既不等同于空字符串

>perl -wE"say 0+(1==0);"
0

>perl -wE"say 0+'';"
Argument "" isn't numeric in addition (+) at -e line 1.
0

也不是0

>perl -wE"say ''.(1==0);"


>perl -wE"say ''.0;"
0

不能保证这种情况会一直存在。而且没有理由依赖这一点。如果你需要特定的值,你可以使用类似的东西

my $formatted = $result ? '1' : '0';

【讨论】:

  • ikegami 您可能会考虑添加指向this answer 的链接以获取更多信息:)
  • 特殊的假值is documented in perlsyn。虽然这并不能完全保证它永远不会改变,但 Perl 5 不会在没有充分理由的情况下破坏向后兼容性。
  • @cjm,Aj 酷,我不知道它被记录在案。这确实使它非常安全。
【解决方案2】:

它们返回一个特殊的 false 值,在字符串上下文中为 "",但在数字上下文中为 0(没有非数字警告)。真正的价值不是那么特别,因为它在任何一种情况下都是 1。 defined() not 返回 undef。

(您可以自己创建类似的值,例如Scalar::Util::dualvar(0,"")。)

【讨论】:

    【解决方案3】:

    因为那是官方手册页,我想说它的确切返回值没有指定。如果 Perl 文档谈论布尔值,那么它几乎总是谈论在布尔上下文中评估所述值:if (defined ...)print while <> 等。在这样的上下文中,几个值评估为假:0undef , ""(空字符串),甚至等于 "0" 的字符串。

    所有其他值在布尔上下文中计算为真,包括臭名昭著的例子"0 but true"

    由于文档含糊不清,我永远不会依赖 defined() 为未定义的情况返回任何特定值。但是,如果您只是在布尔上下文中使用 defined() 而不将其与特定值进行比较,那么您总是可以的。

    好的:print "yes\n" if defined($var)

    不可移植/面向未来:print "yes\n" if defined($var) eq '' 或类似的东西

    【讨论】:

      【解决方案4】:

      它可能永远不会改变,但 perl 没有指定 defined(...) 返回的确切布尔值。

      当使用布尔值时,好的代码不应依赖于用于 true 和 false 的实际值。

      例子:

      # not so great code:
      my $bool = 0;   #
      ...
      if (some condition) {
        $bool = 1;
      }
      
      if ($bool == 1) { ... }
      
      # better code:
      my $bool;       # default value is undef which is false
      
      $bool = some condition;
      
      if ($bool) { ... }
      

      99.9% 的时间没有理由关心用于布尔值的值。 也就是说,在某些情况下,最好使用显式 0 或 1 而不是值的布尔值。示例:

      sub foo {
          my $object = shift;
          ...
          my $bool = $object;
          ...
          return $bool;
      }
      

      意图是使用引用或undef 调用foo(),如果未定义$object,则应返回false。问题是如果$object 被定义foo() 将返回对象本身并因此创建对该对象的另一个引用,这可能会干扰其垃圾收集。所以在这里最好使用显式的布尔值,即:

        my $bool = $object ? 1 : 0;
      

      因此,在使用引用本身来表示其真实性(即其定义性)时要小心,因为可能会创建对引用的不需要的引用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-25
        • 2023-03-13
        • 1970-01-01
        • 2015-01-18
        • 1970-01-01
        • 2011-12-12
        • 1970-01-01
        • 2021-10-29
        相关资源
        最近更新 更多