代码之家  ›  专栏  ›  技术社区  ›  jkramer

在Perl中“0但为真”是什么意思?

  •  61
  • jkramer  · 技术社区  · 16 年前

    14 回复  |  直到 13 年前
        1
  •  59
  •   Kevin Panko Matthew Woodard    7 年前

    这是语言的正常行为。引用 perlsyn 主页:

    号码 0 '0' "" ,空列表 () undef 在布尔上下文中都为false。所有其他值均为真。反面 ! not "" ,但作为一个数字,它是 视为 0

    正因为如此,我们需要有一种回归的方式 来自预期返回的系统调用 0 作为一个(成功的)返回值,并留下一种通过实际返回一个假值来表示失败情况的方法。 "0 but true"

        2
  •  52
  •   geekosaur    13 年前

    因为它是在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 but true" 豁免 -w 抱怨

        3
  •  45
  •   moritz    16 年前

    除了别人说的以外,, "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
    
        4
  •  32
  •   David W.    13 年前

    价值 0 but true 是Perl中的一个特例。虽然在你凡人的眼里,它看起来不像一个数字,但聪明而无所不知的Perl知道它实际上是一个数字。

    假设我有一个子程序,返回两个数字的和:

    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 第二条语句将终止,因为子例程无法添加 母牛 .

    嗯,我可以补充一下 3 -3 . 我只是 0 ,但即使 add 子程序工作了!

    为了解决这个问题,Perl考虑 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...
    

    最后一个statment返回一个 -1

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

    正如我通常对标准函数所做的那样,它不会工作。如果我像在第二个语句中那样使用“barfoo”和“bar”,那么 else 子句将执行,但如果我在第三个中使用“barfoo”和“fu”,则 if 第条将执行。不是我想要的。

    index 返回的子程序 第二项声明和 undef 如果 其他的

        5
  •  25
  •   Andy Lester    14 年前

    您还可以看到字符串 "0E0" used in Perl code ,它的意思是一样的,其中0E0表示以指数表示的0。但是,由于Perl只将“0”、“0”或undef视为false,因此它在布尔上下文中的计算结果为true。

        6
  •  13
  •   Kevin Panko Matthew Woodard    7 年前

    Perl_grok_number_flags in numeric.c .

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

        7
  •  10
  •   user2291758    9 年前

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

      (无输出)

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

      (打印正确)

        8
  •  9
  •   Jon Ericson Homunculus Reticulli    16 年前

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

    Perl方法不能很好地工作的一种情况是,您希望返回一个数字,或者如果函数由于某种原因失败,则返回一个假值。例如,如果您编写一个函数,从文件中读取一行并返回该行的字符数。该函数的常见用法可能是:

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

    请注意,如果特定行上的字符数为0,则 虽然 循环将在文件结束之前结束。所以 行中的字符 函数应为特殊情况0个字符并返回 “0但为真” 相反这样,该功能将按照 虽然

    请注意,这不是语言的内置部分。相反,它利用了Perl将字符串解释为数字的能力。因此,有时会使用其他螫针来代替。 DBI 使用 “0E0” 0 错误的 .

        9
  •  6
  •   Kevin Panko Matthew Woodard    8 年前

    • "" .
    • "0"
    • 使之严格化的东西。

    "0 but true"

    此外,Perl返回 “0但为真” sysseek 是此类函数的一个示例。由于期望值被用作一个数字,所以将Perl编码为将其视为一个数字。因此,将其用作数字时不会发出警告,并且 looks_like_number("0 but true") 返回true。

    http://www.perlmonks.org/?node_id=464548 .

        10
  •  4
  •   kixx    16 年前

    “0但为真”的另一个示例:

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

        11
  •  4
  •   jkramer    16 年前

    我刚刚找到证据,证明字符串“0但为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
    
        12
  •  3
  •   andy    16 年前

    未定义 (即,对于错误情况),则必须注意值0。返回值为false,不应指示错误情况,因此返回“0但为true”将使函数返回值为true,同时在对其进行数学运算时仍返回值0。

        13
  •  3
  •   Frosty    12 年前

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

    考虑:

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

    if($x = find_x)
    {
       print int($x) . "\n";
    }
    
        14
  •  2
  •   F. Hauri    12 年前

    字符串“`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. ...