返回布尔值的 Perl 函数实际上返回啥

Posted

技术标签:

【中文标题】返回布尔值的 Perl 函数实际上返回啥【英文标题】: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,是否会发生变化?

【问题讨论】:

旁注:您可以使用双重否定将任何值转换为其对应的布尔值。这导致!! 伪运算符。对于返回通用的真值或假值而不是一些幻数非常有用。 【参考方案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;

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

【讨论】:

以上是关于返回布尔值的 Perl 函数实际上返回啥的主要内容,如果未能解决你的问题,请参考以下文章

调用返回布尔值的JavaScript函数

如何在java中返回四分之三布尔值的答案

具有布尔返回值的 pl/sql 函数的 OracleType?

始终返回相同布尔值的 Python 函数

返回布尔值的 Java 方法的命名约定

在此上下文中仅允许返回数字或布尔值的变量表达式