为什么是';0';在Perl中为false?

为什么是';0';在Perl中为false?,perl,Perl,首先,我来自C、Java、Python的背景。最近,我开始为我的新工作学习Perl,我对'0'(0-string)为假感到好奇 我已经读到,这种特殊的行为就是为什么Perl必须有操作符来读取文件的原因,所以对我来说,它现在更像是一个设计缺陷。然而,我也知道Perl是一种成熟的语言,我猜这种行为有它的用途,否则它早就被修复了 那么在什么情况下,'0'=false会有用呢?Perl窃取了许多其他语言的特性,包括C、awk、Bourne shell和许多其他语言 在C中,任何0值都是false,任何非

首先,我来自C、Java、Python的背景。最近,我开始为我的新工作学习Perl,我对
'0'
(0-string)为假感到好奇

我已经读到,这种特殊的行为就是为什么Perl必须有
操作符来读取文件的原因,所以对我来说,它现在更像是一个设计缺陷。然而,我也知道Perl是一种成熟的语言,我猜这种行为有它的用途,否则它早就被修复了

那么在什么情况下,
'0'
=false会有用呢?

Perl窃取了许多其他语言的特性,包括C、awk、Bourne shell和许多其他语言

在C中,任何0值都是false,任何非零值都是true。Perl只是使用相同的语义

Perl比C有更多的东西可以在标量或布尔上下文中使用,特别是字符串,这意味着Perl有多个假值

使整数
0
false对于C程序员来说非常有意义。将空字符串
设为false也有意义。由于Perl可以将同一标量视为数字或字符串,因此将字符串
“0”
设为false几乎是不可避免的

例如:

$x = 2;
$x -= 2;
print "x = $x\n"; # prints "x = 0"
if ($x) {
    print "A C programmer would be surprised to see this\n";
}

$x = "";
$x .= chr(48);
# Now $x eq "0", a string value that was built without reference to
# the number zero -- but it's nearly the same thing as the number 0.
print "\$x = $x\n"; # pritn "x = 0"
if ($x) {
    print "A C programmer would be equally surprised to see this\n";
}
$a = "2b";
$b = "3a";
$c = $a + $b;
print $c;
如果Perl是从零开始设计的,而没有从其他语言借用这么多功能,那么它可能会在字符串和数字之间做出更大的区分,而不是将它们作为标量组合在一起。给定这样一种假想的类Perl语言,很可能空字符串和数字
0
为假,但字符串
“0”
为真——您需要显式转换才能将数字
0
转换为字符串
“0”


但是Perl就是这样。

如果你读到它与
有任何关系,那么你读的是不好的源代码;我无法想象这种说法会从何而来

“0”为false,因为几乎所有地方perl都不区分以数字形式和字符串形式存储的数字;在布尔测试中这样做会违反此粒度


在“0”为真的语言(Python、Javascript?)中,我发现“0”为假很奇怪;为什么要对一个字符串而不是另一个字符串进行例外处理?

Perl没有显式类型,它对类型的解释高度依赖于上下文。例如:

$x = 2;
$x -= 2;
print "x = $x\n"; # prints "x = 0"
if ($x) {
    print "A C programmer would be surprised to see this\n";
}

$x = "";
$x .= chr(48);
# Now $x eq "0", a string value that was built without reference to
# the number zero -- but it's nearly the same thing as the number 0.
print "\$x = $x\n"; # pritn "x = 0"
if ($x) {
    print "A C programmer would be equally surprised to see this\n";
}
$a = "2b";
$b = "3a";
$c = $a + $b;
print $c;
收益率5

另一方面

$a = "b2";
$b = "3a";
$c = $a + $b;
print $c;
产量3

而且

$a = "b2";
$b = "3a";
$c = $a.$b;
print $c;
产量b23a


所以“'0'(string)”在您使用它之前不是字符串、数字或布尔,然后它可以是这些东西中的任何一个,这取决于它的使用。在您尝试操作之前,不会确定类型。然后,Perl评估上下文以实现您的意图,并相应地采取行动。这是一个特性,也是为什么在Perl中有很多方法来做事情的原因。当然,它可能会导致大量混乱的代码,但对于单行程序、模糊处理和Perl golf来说非常好。

Perl有许多被视为“false”的值:
unde
、零、字符串
“0”
、空字符串、根据上下文变形为空字符串或空列表的特殊布尔值,以及为布尔上下文重载的对象

其中大多数(未定义、零、空字符串、特殊值、对象)实际上非常有用。字符串
“0”
为false源于perl实现标量和false的方式:标量同时包含字符串部分和数字部分。要确定值是否为false,首先要查看字符串部分。为什么这是必要的

my $false_ish = 0;  # the scalar contains only a number
'' . $false_ish;    # force stringy context. the scalar now contains stringy portion.
if ($false_ish) { ... } # string portion is consulted first...

如果没有这一点,一旦在需要字符串的地方使用数字零,它就会失去其错误性。另一方面,这允许
“0但为真”
,一个数字为零的真字符串,以及
“0E0”
,这是零的科学表示法,但计算结果也是真的。

内部存储格式在Perl中理想情况下永远不会有问题。零是零是零,无论它是否存储在IV、UV、NV、PV等中

事实上,因为它可以,Perl将改变值的存储格式,其方式可能会让您感到惊讶。如果字符串
0
为true,则以下内容将打印“true”:


0在C中也等同于false——它在几种“传统”编程语言中等同于false,可能是由于0与二进制和电路的固有联系,其中0可以表示“不收费”

无论如何,较新的语言通常继承以前的语言行为和解释。0表示“不收费”或“收费是错误的”的二进制含义早已从任何高级编程语言中抽象出来,但即使在最现代的编程语言中,语义的花絮仍然存在


此外,据我所知,这与你在哪里读到的无关。

语言与应用程序不同。一旦字符串“0”的错误被确定,它就不可能被改变,否则会破坏数不清的功能程序。还有“0但错误”的把戏。我认为OP是在
while(){…}
中谈论隐式
定义的
测试。这样,当您从
读取时,循环不会在读取字符串为
'0'
时结束。请尝试
perl-MO=Deparse-E'while(){say}'
以明确地查看它。@JoelBerger:注意
while()
仅当输入的最后一行仅包含字符
0
且没有终止换行符时,才会将
$\ucode>设置为
“0”
。否则,一行上的
0
本身将
$\u
设置为
“0\n”
。这是一个奇怪的情况,但是如果
while()
没有正确处理它,那将是很尴尬的。这更多的是while的特殊情况,而不是
;注意,它也适用于这里:
while(glob“{0,1}”)
和这里:
for(File::Temp->newdir){mkdir“$\u0”;opend