题
谁能解释究竟是什么字"0但真正的"是指在Perl?据我理解,就等于零,在一个整数比较,但计算结果为真正当作为一个布尔。这是正确的?这是一个正常的行为的语言或者是这个特殊字符串视为一种特殊情况的解释?
解决方案
这是语言的正常行为。引用 perlsyn
联机帮助页:
数字
0
,字符串'0'
和""
,空列表()
,和undef
在布尔上下文中都是false。所有其他值都是真的。否定!
或not
的真值,返回特殊的false值。 当评估为字符串时,它被视为""
,但作为数字,它是 视为0
。
因此,需要一种从系统调用返回 0
的方法,该系统调用希望将 0
作为(成功的)返回值返回,并留下通过实际返回错误值来发出故障情况的方法。 " 0但是true"
用于此目的。
其他提示
因为它在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但是true"
免于-w
投诉 关于不正确的数字转换。
除了其他人所说的," 0但是true"
是特殊的,因为它不会在数字上下文中发出警告:
$ 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但是true
是Perl中的一个特例。虽然对于你的凡人来说,它看起来并不像一个数字,明智而且所有人都知道Perl知道它确实是一个数字。
这与Perl子例程返回0值的事实有关,假设例程失败或返回错误值。
想象一下,我有一个子程序,它返回两个数字的总和:
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));
第一个语句不会死,因为子例程将返回 1
。非常好。
第二个语句将会死亡,因为子例程将无法将 cow 添加到 dog 。
并且,第三个声明?
嗯,我可以将 3
添加到 -3
。我只是得到 0
,但是即使 add
子例程工作,我的程序也会死!
为了解决这个问题,Perl认为 0但真正的
是一个数字。如果我的添加子例程不仅返回 0 ,而且 0但是返回,我的第三个语句将起作用。
但 0但是真的是数字零吗?试试这些:
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 子程序是Perl的一个非常古老的部分,并且存在于概念之前 0但真正的在附近。假设返回位于字符串中的子字符串的位置:
index("barfoo", "foo"); #This returns 3
index("barfoo", "bar"); #This returns 0
index("barfoo", "fu"); #This returns ...uh...
最后一个参数返回 -1
。这意味着如果我这样做:
if ($position = index($string, $substring)) {
print "It worked!\n";
}
else {
print "If failed!\n";
}
正如我通常使用标准功能一样,它不起作用。如果我使用“barfoo”和“bar”就像我在第二个语句中所做的那样, else
子句会执行,但是如果我使用了“barfoo”,那么和“fu”与第三个一样, if
子句将执行。不是我想要的。
但是,如果 index
子例程返回 0但第二个语句为true ,第三个语句返回 undef
,我的 if
/ else
子句可行。
你也可以看到的字符串 "0E0"用在Perl码, 和这意味着同样的事情,其中0E0只是指0写入指数表示。然而,由于Perl只认为"0"、"或民主基金作为虚假的,它计算结果为真正的布尔上下文。
它在Perl的源代码中是硬编码的,特别是在 numeric.c中的Perl_grok_number_flags 。
阅读该代码,我发现字符串“无限” (不区分大小写)也通过了looks_like_number测试。我不知道。
在整数情况下,它评估为0(数字的一部分开始时string)和为零。在一个标方面,这是一个非空值,所以它是真实的。
if (int("0 but true")) { print "zero"; }
(no output)
if ("0 but true") { print "true"; }
(打印件的真实)
0 在Perl(以及与C相关的其他语言)中表示false。在大多数情况下,这是一种合理的行为。其他语言(例如Lua)将 0 视为true,并提供另一个令牌(通常为 nil 或 false )来表示非真值。
Perl方式不能很好地工作的一种情况是当你想要返回一个数字时,或者如果函数由于某种原因失败,则返回false值。例如,如果您编写的函数从文件中读取一行并返回该行上的字符数。该函数的常见用法可能是:
while($c = characters_in_line($file)){
...
};
请注意,如果特定行上的字符数为0, while 循环将在文件结束之前结束。因此 characters_in_line 函数应该是特殊情况0字符并返回'0而不是true'。这样,该函数将在 while 循环中按预期工作,但如果将其用作数字,也会返回正确的答案。
请注意,这不是语言的内置部分。相反,它利用了Perl将字符串解释为数字的能力。因此有时会使用其他刺痛。例如, DBI 使用" 0E0" 。在数值上下文中进行评估时,它们返回 0 ,但在布尔上下文中, false 。
东西都是假:
""
."0"
.- 事情转换成字符串到的那些。
"0 but true"
是不是其中的一个,所以它不是虚假的。
此外,Perl返回 "0 but true"
其中一些预期在以信号,功能成功,即使它返回零。 sysseek 是一例这样的功能。由于价值预计可用作一个数字,Perl编码,以考虑它是一个数字。结果,没有发出警告时,使用它作为一个号码, looks_like_number("0 but true")
返回正确的。
其他的"真正的零",可以发现在 http://www.perlmonks.org/?node_id=464548.
“0但是真实”的另一个例子:
DBI模块使用“0E0”和“0E0”。作为不影响任何记录的UPDATE或DELETE查询的返回值。它在布尔上下文中计算为true(表示查询已正确执行),在数字上下文中为0,表示查询未更改任何记录。
我刚刚发现字符串“0但是真实”的证明实际上已经内置到翻译中,就像这里的一些人已经回答:
$ 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
如果要编写一个返回整数值的函数,或者 false 或 undef (即错误情况),那么你必须注意价值零。返回它是错误的并且不应该指示错误条件,因此返回“0但是为真”。使函数返回值为true,同时在对其进行数学运算时仍然返回零值。
“0但是真实的”是一个字符串就像任何其他字符串一样,但由于perl的语法,它可以起到一个有用的作用,即从函数返回整数零而结果不是“假”(在perl眼中)。
字符串不必是“0但是为真”。 “0但是假”在布尔意义上仍然是“真实的”。
考虑:
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”和“0”。作为其输出:
if($x = find_x)
{
print int($x) . "\n";
}
字符串“0但是真的”仍然是一个特例:
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: ||
......不要忘记RTFM!
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. ...