Perl定义的函数(和许多其他函数)返回“布尔值”。
鉴于 Perl 实际上没有 Boolean 类型(并且使用1表示true,使用0或undef表示false),Perl 语言是否准确指定了布尔值返回的内容?例如,将defined(undef)
返回0或undef,是否会发生变化?
在几乎所有情况下(即除非有理由不这样做),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';
它们返回一个特殊的 false 值,在字符串上下文中为 "",但在数字上下文中为 0(没有非数字警告)。真正的价值不是那么特别,因为它在任何一种情况下都是 1。defined() 不返回undef。
(您可以自己创建类似的值,例如Scalar::Util::dualvar(0,"")
。)
它可能永远不会改变,但是 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;
所以要小心使用引用本身来表示它的真实性(即它的定义性),因为可能会创建对引用的不需要的引用。
由于那是官方手册页,我会说没有指定它的确切返回值。如果 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 ''
或类似的东西