这很奇怪。 以下内容:
$sum = !0;
print $sum;
按照您的预期打印1。但是这个
$sum = !1;
print $sum;
什么都没打印出来。为什么呢?
答案 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'
从中我们学到了几件事。
前两项并非令人兴奋:
!1
和not 1
的行为基本相同。 ~1
是不同的(不是按位)。现在,有趣的项目:
0+''
)的警告,但在添加0+!1
时没有生成警告。发生了一些可疑的事情,而且鱼腥味与Perl中的特殊标量背景有关。在这种情况下,数字和字符串上下文之间的区别。并且能够创建在每个上下文中具有不同值的变量,也称为双变量。
看起来!1
返回一个双变量,它在数字上下文中返回0,在字符串上下文中返回空字符串。
最后的双变量测试表明,自制双变量的工作方式与!1
相同。
与许多Perl功能一样,双变量最初似乎无视期望,并且可能令人困惑。然而,像其他功能一样,使用得当它们会让生活变得更加轻松。
据我所知,0
和''
的双变量是唯一定义的值,它将在所有标量上下文中返回false。因此,!1
是一个非常合理的回报值。有人可能会说undef
是一个很好的错误结果,但是未初始化的变量与假值无法区分。此外,尝试打印或添加布尔结果会受到不必要的警告的困扰。
如果你$!
,另一个着名的双变量是$OS_ERROR
或use English
。在数字形式中,您将获得错误代码,以字符串形式,为您翻译错误代码。
总而言之,你没有得到任何东西,你没有得到一个空字符串,你没有得到零。
您将获得一个同时为空字符串且为0的变量。
答案 3 :(得分:3)
!
运算符执行布尔运算。 ""
(空字符串)与false
一样0
。 1
是一个方便的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);