“0但真实”是什么意思? Perl 中的意思是?

发布于 2024-10-22 06:40:39 字数 115 浏览 3 评论 0原文

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

Can someone explain what exactly the string "0 but true" means in Perl? As far as I understand, it equals zero in an integer comparison, but evaluates to true when used as a boolean. Is this correct? Is this a normal behavior of the language or is this a special string treated as a special case in the interpreter?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

冬天旳寂寞 2024-10-29 06:40:40

这是语言的正常行为。引用 perlsyn 联机帮助页:

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

因此,需要有一种方法可以从希望返回 0 作为(成功)返回值的系统调用中返回 0,并留出一种方式来发出信号实际上返回错误值的失败案例。 “0 but true” 就是为了这个目的。

It's normal behaviour of the language. Quoting the perlsyn manpage:

The number 0, the strings '0' and "", the empty list (), and undef
are all false in a boolean context. All other values are true. Negation
of a true value by ! or not returns a special false value.
When evaluated as a string it is treated as "", but as a number, it is
treated as 0.

Because of this, there needs to be a way to return 0 from a system call that expects to return 0 as a (successful) return value, and leave a way to signal a failure case by actually returning a false value. "0 but true" serves that purpose.

⒈起吃苦の倖褔 2024-10-29 06:40:40

因为它在 Perl 核心中被硬编码为将其视为数字。这是一个让 Perl 的约定和 ioctl 的约定一起发挥作用的 hack;来自perldoc -f ioctl:

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

如果操作系统返回:则 Perl 返回:

    -1 未定义值
     0 字符串“0 但为真”
其他任何那个数字

因此,Perl 在成功时返回 true,在失败时返回 false,但你
仍然可以轻松确定返回的实际值
操作系统:

$retval = ioctl(...) || -1;
printf "系统返回%d\n", $retval;

特殊字符串“0 but true”不受-w投诉
关于不正确的数字转换。

Because it's hardcoded in the Perl core to treat it as a number. This is a hack to make Perl's conventions and ioctl's conventions play together; from perldoc -f ioctl:

The return value of ioctl (and fcntl) is as follows:

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number

Thus Perl returns true on success and false on failure, yet you
can still easily determine the actual value returned by the
operating system:

$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;

The special string "0 but true" is exempt from -w complaints
about improper numeric conversions.

淡淡離愁欲言轉身 2024-10-29 06:40:40

除了其他人所说的之外,“0 but 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

Additionally to what others said, "0 but true" is special-cased in that it doesn't warn in numeric context:

$ 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
携余温的黄昏 2024-10-29 06:40:40

0 but 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 but true 视为数字。如果我的 add 子例程不仅返回 0,而且返回 0 but true,则我的第三条语句将起作用。

但是 0 but true 是数字零吗?试试这些:

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 但 true 就在附近。假设返回子字符串在字符串中的位置:

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 but true,对于第三条语句返回 undef,则我的 if/else 子句会起作用。

The value 0 but true is a special case in Perl. Although to your mere mortal eyes, it doesn't look like a number, wise and all knowing Perl understands it really is a number.

It has to do with the fact that when a Perl subroutine returns a 0 value, it is assumed that the routine failed or returned a false value.

Imagine I have a subroutine that returns the sum of two numbers:

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));

The first statement won't die because the subroutine will return a 1. That's good.
The second statement will die because the subroutine won't be able to add cow to dog.

And, the third statement?

Hmmm, I can add 3 to -3. I just get 0, but then my program will die even though the add subroutine worked!

To get around this, Perl considers 0 but true to be a number. If my add subroutine returns not merely 0, but 0 but true, my third statement will work.

But is 0 but true a numeric zero? Try these:

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";

Yup, it's zero!

The index subroutine is a very old piece of Perl and existed before the concept of 0 but true was around. It is suppose to return the position of the substring located in the string:

index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...

The last statment returns a -1. Which means if I did this:

if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}

As I normally do with standard functions, it wouldn't work. If I used "barfoo" and "bar" like I did in the second statement, The else clause would execute, but if I used "barfoo" and "fu" as in the third, the if clause would execute. Not what I want.

However, if the index subroutine returned 0 but true for the second statement and undef for the third statement, my if/else clause would have worked.

吻风 2024-10-29 06:40:40

您还可能会看到 Perl 代码中使用的字符串"0E0",其含义相同事情,其中​​ 0E0 只是表示以指数表示法书写的 0。然而,由于 Perl 只将“0”、“”或 undef 视为 false,因此它在布尔上下文中计算结果为 true。

You may also see the string "0E0" used in Perl code, and it means the same thing, where 0E0 just means 0 written in exponential notation. However, since Perl only considers "0", '' or undef as false, it evaluates to true in a boolean context.

淡墨 2024-10-29 06:40:40

它是硬编码在 Perl 的源代码中,特别是在 Perl_grok_number_flags 中的 numeric 中.c

阅读该代码我发现字符串“infinity”(不区分大小写)也通过了looks_like_number 测试。我不知道这一点。

It's hard-coded in Perl's source code, specifically in Perl_grok_number_flags in numeric.c.

Reading that code I discovered that the string "infinity" (case insensitive) passes the looks_like_number test too. I hadn't known that.

愿得七秒忆 2024-10-29 06:40:40

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

  • if (int("0 但为真")) { print "零"; }

    (无输出)

  • if ("0 but true") { print "true"; }

    (打印 true)

In an integer context, it evaluates to 0 (the numeric part at the beginning of the string) and is zero. In a scalar context, it's a non-empty value, so it is true.

  • if (int("0 but true")) { print "zero"; }

    (no output)

  • if ("0 but true") { print "true"; }

    (prints true)

不疑不惑不回忆 2024-10-29 06:40:40

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

Perl 方法不太有效的一种情况是,您想要返回一个数字,或者如果函数由于某种原因失败,则返回一个假值。例如,如果您编写一个函数从文件中读取一行并返回该行的字符数。该函数的常见用法可能类似于:

while($c = characters_in_line($file)){
    ...
};

请注意,如果特定行上的字符数为 0,则 while 循环将在文件结束之前结束。因此 characters_in_line 函数应该将 0 个字符特殊化并返回 '0 but true'。这样,该函数将在 while 循环中按预期工作,而且如果将其用作数字,也会返回正确的答案。

请注意,这不是该语言的内置部分。相反,它利用 Perl 将字符串解释为数字的能力。所以有时会用其他蜇刺来代替。例如,DBI 使用“0E0”。在数字上下文中计算时,它们返回0,但在布尔上下文中,返回false

0 means false in Perl (and other languages related to C). For the most part, that's a reasonable behavior. Other languages (Lua for instance) treat 0 as true and provide another token (often nil or false) to represent a non-true value.

One case where the Perl way doesn't work so well is when you want to return either a number or, if the function fails for some reason, a false value. For instance, if you write a function that reads a line from a file and returns the number of characters on the line. A common usage of the function might be something like:

while($c = characters_in_line($file)){
    ...
};

Notice that if the number of characters on a particular line is 0, the while loop will end before the end of the file. So the characters_in_line function should special case 0 characters and return '0 but true' instead. That way the function will work as intended in the while loop, but also return the correct answer should it be used as a number.

Note that this isn't a built in part of the language. Rather it takes advantage of Perl's ability to interpret a string as a number. So other stings are sometimes used instead. DBI uses "0E0", for instance. When evaluated in numeric context, they return 0, but in boolean context, false.

抱着落日 2024-10-29 06:40:40

错误的事情:

  • ""
  • <代码>“0”。
  • 与那些串连的东西。

“0 but true” 不是其中之一,因此它不是 false。

此外,Perl 返回“0 but true”,其中需要一个数字,以便表明函数成功,即使它返回零。 sysseek 就是此类函数的一个示例。由于该值预计将用作数字,因此 Perl 编码为将其视为数字。因此,当它用作数字时,不会发出警告,并且 looks_like_number("0 but true") 返回 true。

其他“真正的零”可以在 http://www.perlmonks.org/?node_id=464548< /a>.

Things that are false:

  • "".
  • "0".
  • Things that stringify to those.

"0 but true" is not one of those, so it's not false.

Furthermore, Perl returns "0 but true" where a number is expected in order to signal that a function succeeded even though it returned zero. sysseek is an example of such a function. Since the value is expected to be used as a number, Perl is coded to consider it to be a number. As a result, no warnings are issued when it's used as a number, and looks_like_number("0 but true") returns true.

Other "true zeroes" can be found at http://www.perlmonks.org/?node_id=464548.

执着的年纪 2024-10-29 06:40:40

“0 but true”的另一个示例:

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

Another example of "0 but true":

The DBI module uses "0E0" as a return value for UPDATE or DELETE queries that didn't affect any records. It evaluates to true in a boolean context (indicating that the query was executed properly) and to 0 in a numeric context indicating that no records were changed by the query.

旧夏天 2024-10-29 06:40:40

我刚刚发现证据表明字符串“0 but 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

I just found proof that the string "0 but true" is actially built into the interpreter, like some people here already answered:

$ 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
烂人 2024-10-29 06:40:40

当您想要编写一个返回整数值或falseundef(即错误情况)的函数时,您必须注意值零。返回它是 false 并且不应该指示错误条件,因此返回“0 but true”使函数返回值 true,同时在完成数学运算时仍然传回值零。

When you want to write a function that returns either an integer value, or false or undef (i.e. for the error case) then you have to watch out for the value zero. Returning it is false and shouldn't indicate the error condition, so returning "0 but true" makes the function return value true while still passing back the value zero when math is done on it.

不离久伴 2024-10-29 06:40:40

“0 but true”是一个字符串,就像任何其他字符串一样,但由于 Perl 的语法,它可以起到有用的作用,即从函数返回整数零,而不会导致结果为“false”(在 Perl 看来)。

并且字符串不必是“0 but true”。 “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”作为其输出:

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

"0 but true" is a string just like any other but because of perl's syntax it can serve a useful purpose, namely returning integer zero from a function without the result being "false"(in perl's eyes).

And the string need not be "0 but true". "0 but false" is still "true"in the boolean sense.

consider:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false

The upshot of all of this is you can have:

sub find_x()

and have this code be able to print "0" as its output:

if($x = find_x)
{
   print int($x) . "\n";
}
も让我眼熟你 2024-10-29 06:40:40

字符串“0 but true”仍然是一个特殊情况:

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. ...

The string ``0 but true'' is still a special case:

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

give the following: (note the ``warning''!)

'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: ||

... and don't forget to 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. ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文