为什么!1在Perl中没有给我任何东西?

时间:2009-07-16 01:12:31

标签: perl boolean

这很奇怪。 以下内容:

$sum = !0;
print $sum;

按照您的预期打印1。但是这个

$sum = !1;
print $sum;

什么都没打印出来。为什么呢?

5 个答案:

答案 0 :(得分:41)

小心:你所写的不是你认为它正在做的事情。请记住,perl没有真正的布尔数据类型。它有标量,散列,列表和参考。那么它处理真/假值的方式是上下文的。除了未定义的变量,空列表,空字符串和数字0之外,perl中的所有内容都评估为“true”。

您的代码正在执行的操作是采用值为“false”的值的倒数,该值可以是上面列表中没有的任何值。按照惯例,为了简单起见,perl返回1(尽管你不应该依赖它;它可以很好地返回包含一系列随机数的列表,因为它也会评估为“true”。)

当您要求评估为“true”的值的倒数时,会发生类似的事情。什么实际打印出来的不是“没有”,它是空字符串(''),正如我所提到的,它在布尔表达式中求值为“false”。你可以查看:

print "This evaluates to false\n" if( (!1) eq '');

如果你问为什么perl吐出空字符串而不是其他一个“假”值,那么,这可能是因为perl是为了处理字符串而且这是一个非常合理的字符串可以回传。

答案 1 :(得分:9)

仅返回布尔结果的运算符将始终返回1表示true,而特殊的false值在字符串上下文中为“”,在数字上下文中为0。

答案 2 :(得分:6)

以下是您已经获得的其他优秀答案的附录。

不是不是

考虑以下代码来测试每个Perl的'not'运算符:

#!/usr/bin/perl

use strict;
use warnings;

for( '!1', 'not 1', '~0' ) {
    my $value = eval;
    my $zero_plus = 0 + $value;

    print join "\n", 
        "\nExpression: $_",
        "Value:     '$value'",
        "Defined:   " . defined $value,
        "Length:    " . length($value),
        "Plus:      " . +$value,
        "Plus Zero: '$zero_plus'",
        '';
}

print "\nTest addition for a literal null string:  ";
print 0+'', "\n";

use Scalar::Util qw(dualvar);

{   # Test a dualvar 
    my $value = dualvar 0, '';
    my $zero_plus = 0+$value;

    print join "\n", 
        "\nExpression: dualvar",
        "Value:     '$value'",
        "Defined:   " . defined $value,
        "Length:    " . length($value),
        "Plus:      " . +$value,
        "Plus Zero: '$zero_plus'",
        '';

}

执行它会导致以下结果。请注意警告消息:

Argument "" isn't numeric in addition (+) at test.pl line 21.

Expression: !1
Value:     ''
Defined:   1
Length:    0
Plus:
Plus Zero: '0'

Expression: not 1
Value:     ''
Defined:   1
Length:    0
Plus:
Plus Zero: '0'

Expression: ~0
Value:     '4294967295'
Defined:   1
Length:    10
Plus:      4294967295
Plus Zero: '4294967295'

Test addition for a literal null string:  0

Expression: dualvar
Value:     ''
Defined:   1
Length:    0
Plus:
Plus Zero: '0'

从中我们学到了几件事。

前两项并非令人兴奋:

  • !1not 1的行为基本相同。
  • 毫无疑问,~1是不同的(不是按位)。

现在,有趣的项目:

  • 虽然我们收到了第21行(0+'')的警告,但在添加0+!1时没有生成警告。

需要两个纠结

发生了一些可疑的事情,而且鱼腥味与Perl中的特殊标量背景有关。在这种情况下,数字和字符串上下文之间的区别。并且能够创建在每个上下文中具有不同值的变量,也称为双变量。

看起来!1返回一个双变量,它在数字上下文中返回0,在字符串上下文中返回空字符串。

最后的双变量测试表明,自制双变量的工作方式与!1相同。

但这是一件好事

与许多Perl功能一样,双变量最初似乎无视期望,并且可能令人困惑。然而,像其他功能一样,使用得当它们会让生活变得更加轻松。

据我所知,0''的双变量是唯一定义的值,它将在所有标量上下文中返回false。因此,!1是一个非常合理的回报值。有人可能会说undef是一个很好的错误结果,但是未初始化的变量与假值无法区分。此外,尝试打印或添加布尔结果会受到不必要的警告的困扰。

如果你$!,另一个着名的双变量是$OS_ERRORuse English。在数字形式中,您将获得错误代码,以字符串形式,为您翻译错误代码。

这不是什么,它是空的,但它没有了

总而言之,你没有得到任何东西,你没有得到一个空字符串,你没有得到零。

您将获得一个同时为空字符串且为0的变量。

答案 3 :(得分:3)

!运算符执行布尔运算。 ""(空字符串)与false一样01是一个方便的true值。除了产生! / true值之外,不应依赖false做任何其他事情。依赖于超出该值的确切值是危险的,并且可能在Perl版本之间发生变化。

答案 4 :(得分:3)

请参阅perldoc perlsyn

  

真相与虚假

     

数字0,字符串'0'和'',   空列表()和undef都是   布尔上下文中为false。所有其他   价值观是真的。否定一个真实的   价值!或不返回特殊   虚假价值。当评估为   字符串它被视为'',但作为一个   数字,它被视为0。

在那里,如果您将值打印为数字,您将获得0而不是空字符串:

printf "%d\n", $_ for map { !$_ } (1, 0);

print 0 + $_, "\n" for map { !$_ } (1, 0);

将这些与

进行比较
printf "%s\n", $_ for map { !$_ } (1, 0);

print $_, "\n" for map { !$_ } (1, 0);