【问题标题】:Why does Time::HiRes::stat break list subscripting?为什么 Time::HiRes::stat 会中断列表下标?
【发布时间】:2012-01-12 03:48:52
【问题描述】:

我不知道这里发生了什么。下面的8个是哪里来的?

Time::HiRes 提供了stat 的重载,它扩展了获得高分辨率的时间(我的系统支持)。

$ perl  -MTime::HiRes -e 'print +(stat("foo"))[8], "\n"'              # V1
1322915623
$ perl  -MTime::HiRes=stat -e 'print +(stat("foo"))[8], "\n"'         # V2
8
$ perl  -MTime::HiRes=stat -e '@a = stat("foo"); print $a[8], "\n"'   # V3
1322915623

那个特定的文件没有高分辨率的时间戳,但这不是秘密:秘密是 V2,它打印 8。事实上,它总是在方括号中打印数字。

显而易见的答案,它的解析方式不同,似乎并不正确:

$ perl -MO=Deparse -MTime::HiRes -e 'print +(stat("foo"))[8], "\n"'         # V1
use Time::HiRes;
print((stat 'foo')[8], "\n");
-e syntax OK
$ perl -MO=Deparse -MTime::HiRes=stat -e 'print +(stat("foo"))[8], "\n"'    # V2
use Time::HiRes (split(/,/, 'stat', 0));
print((stat 'foo')[8], "\n");
-e syntax OK

它们解析相同(use Time::HiRes 的不同选项除外)。

如果我以类似的语法使用我自己的函数,它可以正常工作,即使我从我的函数中返回一些愚蠢的东西,我也无法得到“错误”的答案:

$ perl -e 'sub bar() { return qw(a b c d e f g h i j) }; print +(bar)[8], "\n"'
i
$ perl -e 'sub bar() { return undef }; print +(bar)[8], "\n"'

$

这是 Debian 的 perl 软件包,版本 5.14.2-5。我使用 5.10.1-17squeeze2 得到相同的结果。

上面的 V2 是如何产生 8 的?我是在某种程度上误解了 Perl 语法,还是只需要提交错误报告?

编辑:正如@cjm 所说,这是一个错误。根据报告,它已在 Time-HiRes-1.9725 中修复。

【问题讨论】:

    标签: arrays perl time-hires


    【解决方案1】:

    这绝对是一个错误,虽然我不确定它是在核心 Perl 中还是在 Time::HiRes 中。我在 Gentoo 上使用 Perl 5.14.2(以及 5.8.9 和 5.10.0)得到了相同的结果。你有没有注意到你在下标中放什么并不重要?

    $ perl -MTime::HiRes=stat -e 'print +(stat("foo"))[215.4], "\n"' 
    215.4
    $ perl -MTime::HiRes=stat -e 'print +(stat("foo"))["bar"], "\n"'
    bar
    

    我可能会先report it in Time::HiRes

    注意:虽然它们的解析相同,但它们确实会生成不同的操作码(由于调用内置子程序和用户定义子程序之间的差异):

    $ perl -MO=Concise -MTime::HiRes -e 'print +(stat("foo"))[8], "\n"' 
    c  <@> leave[1 ref] vKP/REFC ->(end)
    1     <0> enter ->2
    2     <;> nextstate(main 271 -e:1) v:{ ->3
    b     <@> print vK ->c
    3        <0> pushmark s ->4
    9        <2> lslice lK/2 ->a
    -           <1> ex-list lK ->6
    4              <0> pushmark s ->5
    5              <$> const(IV 8) s ->6
    -           <1> ex-list lK ->9
    6              <0> pushmark s ->7
    8              <1> stat lK/1 ->9
    7                 <$> const(PV "foo") s ->8
    a        <$> const(PV "\n") s ->b
    -e syntax OK
    
    $ perl -MO=Concise -MTime::HiRes=stat -e 'print +(stat("foo"))[8], "\n"' 
    e  <@> leave[1 ref] vKP/REFC ->(end)
    1     <0> enter ->2
    2     <;> nextstate(main 271 -e:1) v:{ ->3
    d     <@> print vK ->e
    3        <0> pushmark s ->4
    b        <2> lslice lK/2 ->c
    -           <1> ex-list lK ->6
    4              <0> pushmark s ->5
    5              <$> const(IV 8) s ->6
    -           <1> ex-list lK ->b
    6              <0> pushmark s ->7
    a              <1> entersub[t1] lKS/TARG,1 ->b
    -                 <1> ex-list lK ->a
    7                    <0> pushmark s ->8
    8                    <$> const(PV "foo") sM ->9
    -                    <1> ex-rv2cv sK ->-
    9                       <$> gv(*stat) s ->a
    c        <$> const(PV "\n") s ->d
    -e syntax OK
    

    【讨论】:

    【解决方案2】:

    我从未使用过命令行执行,所以我谈到了它的工作原理。

    在应该返回数组的函数上使用下标时,我看到了意外的结果。

    $y = localtime()[5];    # failed for me (I forget just how)
    

    但是

    $y = (localtime())[5];  # worked fine
    

    这向我暗示了 Perl(我的实现)中的一个错误。更好的测试可能是在实际脚本中尝试:

    use Time::HiRes qw(stat);
    
    my @x = stat("foo");
    
    print $x[8],"\n";
    

    我在 WinXP 上使用 ActiveState 的 Perl,所以我的结果可能不一样。不过,我认为用非常简单的代码尝试它可能会很有用,看看它做了什么。

    【讨论】:

    • 这不是错误:Perl 的list indexing 语法是(LIST)[INDEX]。括号是必需的。 (但是,derobert 和 cjm 观察到的行为一个错误。)
    猜你喜欢
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    相关资源
    最近更新 更多