12

Perl定义的函数(和许多其他函数)返回“布尔值”。

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

4

4 回答 4

13

在几乎所有情况下(即除非有理由不这样做),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';
于 2012-11-22T22:00:47.063 回答
6

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

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

于 2012-11-22T21:48:15.790 回答
3

它可能永远不会改变,但是 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;
}

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

  my $bool = $object ? 1 : 0;

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

于 2012-11-22T21:55:35.703 回答
3

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

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

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

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

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

于 2012-11-22T21:48:30.373 回答