返回布尔值的 Perl 函数实际上返回啥
Posted
技术标签:
【中文标题】返回布尔值的 Perl 函数实际上返回啥【英文标题】:What do Perl functions that return Boolean actually return返回布尔值的 Perl 函数实际上返回什么 【发布时间】:2012-11-11 07:09:24 【问题描述】:Perl defined 函数(以及许多其他函数)返回“布尔值”。
鉴于 Perl 实际上没有布尔类型(并且使用像 1 这样的值来表示 true,以及 0 或 undef for false) Perl 语言是否准确指定布尔值返回的内容?例如,defined(undef)
会返回 0 还是 undef,是否会发生变化?
【问题讨论】:
旁注:您可以使用双重否定将任何值转换为其对应的布尔值。这导致!!
伪运算符。对于返回通用的真值或假值而不是一些幻数非常有用。
【参考方案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 <>
等。在这样的上下文中,几个值评估为假:0
、undef
, ""
(空字符串),甚至等于 "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;
因此,在使用引用本身来表示其真实性(即其定义性)时要小心,因为可能会创建对引用的不需要的引用。
【讨论】:
以上是关于返回布尔值的 Perl 函数实际上返回啥的主要内容,如果未能解决你的问题,请参考以下文章