什么是;“0但为真”;用Perl是什么意思?

什么是;“0但为真”;用Perl是什么意思?,perl,integer,boolean,Perl,Integer,Boolean,有人能解释一下字符串“0但是true”在Perl中的确切含义吗?据我所知,它在整数比较中等于零,但在用作布尔值时计算结果为真。这是正确的吗?这是语言的正常行为,还是在解释器中作为特例处理的特殊字符串?在整数上下文中,它的计算结果为0(字符串开头的数字部分)且为零。在标量上下文中,它是非空值,因此为真 if(int(“0但true”){print“zero”} (无输出) if(“0但为真”){print“true”;} (打印正确) 当您想要编写一个返回整数值、false或undef(即错误情

有人能解释一下字符串“0但是true”在Perl中的确切含义吗?据我所知,它在整数比较中等于零,但在用作布尔值时计算结果为真。这是正确的吗?这是语言的正常行为,还是在解释器中作为特例处理的特殊字符串?

在整数上下文中,它的计算结果为0(字符串开头的数字部分)且为零。在标量上下文中,它是非空值,因此为真

  • if(int(“0但true”){print“zero”}

    (无输出)

  • if(“0但为真”){print“true”;}

    (打印正确)


当您想要编写一个返回整数值、false或undef(即错误情况)的函数时,必须注意值为零。返回值为false,不应指示错误情况,因此返回“0但为true”将使函数返回值为true,同时在对其进行数学运算时仍返回值0。

这是该语言的正常行为。引用手册页:

数字
0
、字符串
'0'
“”
、空列表
()
unde
在布尔上下文中都为false。所有其他值均为真。否定 通过
获得真实值
not
返回一个特殊的假值。 当作为字符串计算时,它将被视为
,但作为数字,它是 视为
0


因此,需要有一种方法从系统调用返回
0
,该系统调用预期将
0
作为(成功的)返回值返回,并留下一种方法通过实际返回假值来表示故障情况<代码>“0但为真”用于此目的。

除了其他人所说的以外,
“0但为真”
是一种特殊情况,因为它不会在数字上下文中发出警告:

$ perl -wle 'print "0 but true" + 3'
3
$ perl -wle 'print "0 but crazy" + 3'
Argument "0 but crazy" isn't numeric in addition (+) at -e line 1.
3
“0 but true”是一个字符串,与其他任何字符串一样,但由于perl的语法,它可以起到有用的作用,即从函数返回整数零,而结果不会是“false”(在perl看来)

并且字符串不必为“0”,而必须为true。“0但false”在布尔意义上仍然是“true”

考虑:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false
所有这些的结果是,您可以:

sub find_x()
并使此代码能够打印“0”作为其输出:

if($x = find_x)
{
   print int($x) . "\n";
}

0在Perl(以及其他与C相关的语言)中表示false。在大多数情况下,这是一种合理的行为。其他语言(例如Lua)将0视为真,并提供另一个标记(通常为nilfalse)来表示非真值

Perl方法不能很好地工作的一种情况是,您希望返回一个数字,或者如果函数由于某种原因失败,则返回一个假值。例如,如果您编写一个函数,从文件中读取一行并返回该行的字符数。该函数的常见用法可能是:

while($c = characters_in_line($file)){
    ...
};
请注意,如果特定行上的字符数为0,则while循环将在文件结尾之前结束。因此,函数中的字符应为0个字符的特殊情况,并返回'0但为true'。这样,函数将在while循环中按预期工作,但如果它被用作数字,也会返回正确答案


请注意,这不是语言的内置部分。相反,它利用了Perl将字符串解释为数字的能力。因此,有时会使用其他螫针来代替<例如,strong>DBI
使用“0E0”。在数值上下文中求值时,它们返回0,但在布尔上下文中,false

您也可以看到字符串,它表示相同的内容,其中0E0表示以指数表示的0。但是,由于Perl仅将“0”、“0”或undef视为false,因此在布尔上下文中它的计算结果为true。

另一个“0但为true”的示例:


DBI模块使用“0E0”作为不影响任何记录的更新或删除查询的返回值。它在布尔上下文中的计算结果为true(表示查询已正确执行),在数字上下文中的计算结果为0,表示查询未更改任何记录。

我刚刚找到证据,证明字符串“0但true”实际上已内置到解释器中,就像这里的一些人已经回答的那样:

$ strings /usr/lib/perl5/5.10.0/linux/CORE/libperl.so | grep -i true
Perl_sv_true
%-p did not return a true value
0 but true
0 but true
虚假的东西:

  • “0”
  • 使之严格化的东西
“0但是true”
不是其中之一,所以它不是false

此外,Perl返回
“0,但返回true”
,其中需要一个数字来表示函数成功,即使它返回了零。是此类函数的一个示例。由于期望值被用作一个数字,所以将Perl编码为将其视为一个数字。因此,将其用作数字时不会发出警告,
看起来像数字(“0但为真”)
返回真


其他“真零”可以在中找到。

,因为它在Perl内核中硬编码为数字。这是一种使Perl的约定和
ioctl
的约定一起发挥作用的技巧;从
perldoc-f ioctl

ioctl
(和
fcntl
)的返回值如下:

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number
因此,Perl在成功时返回true,在失败时返回false,但是 仍然可以轻松确定 操作系统:

$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;
特殊字符串
“0 but true”
免于
-w
投诉 关于不正确的数字转换


它是在Perl的源代码中硬编码的,特别是在

阅读该代码时,我发现字符串“infinity”(不区分大小写)也通过了looks_like_number测试。我
die "You can only add two numbers\n" if (not add(3, -2));
die "You can only add two numbers\n" if (not add("cow", "dog"));
die "You can only add two numbers\n" if (not add(3, -3));
my $value = "0 but true";
print qq(Add 1,000,000 to it: ) . (1_000_000 + $value) . "\n";
print "Multiply it by 1,000,000: " . 1_000_000 * $value . "\n";
index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...
if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}
for arg in "'0 but true'" "1.0*('0 but true')" \
           "1.0*('0 but false')" 0 1 "''" "0.0" \
           "'false'" "'Ja'" "'Nein'" "'Oui'" \
           "'Non'" "'Yes'" "'No'" ;do
    printf "%-32s: %s\n" "$arg" "$(
        perl -we '
            my $ans=eval $ARGV[0];
            $ans=~s/^(Non?|Nein)$//;
            if ($ans) {
                printf "true:  |%s|\n",$ans
            } else {
                printf "false: |%s|", $ans
          };' "$arg"
        )"
    done
'0 but true'                    : true:  |0 but true|
1.0*('0 but true')              : false: |0|
Argument "0 but false" isn't numeric in multiplication (*) at (eval 1) line 1.
1.0*('0 but false')             : false: |0|
0                               : false: |0|
1                               : true:  |1|
''                              : false: ||
0.0                             : false: |0|
'false'                         : true:  |false|
'Ja'                            : true:  |Ja|
'Nein'                          : false: ||
'Oui'                           : true:  |Oui|
'Non'                           : false: ||
'Yes'                           : true:  |Yes|
'No'                            : false: ||
man -P'less +"/0 but [a-z]*"' perlfunc

       ... "fcntl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.  This string is true in boolean
           context and 0 in numeric context.  It is also exempt from the
           normal -w warnings on improper numeric conversions. ...