7

ここで何が起こっているのか理解できません。以下の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で修正されています。

4

2 に答える 2

3

コア 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

おそらく最初に 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
于 2011-12-03T14:45:44.923 に答える
0

私はコマンドライン実行を使用したことがないので、その仕組みの奇妙な点について話します。

配列を返す必要がある関数で添え字を使用すると、予期しない結果が生じることがあります。

$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 を使用しているため、結果が異なる場合があります。それでも、非常に単純なコードで試してみて、それが何をするかを確認することは役立つと思います。

于 2011-12-08T03:30:16.480 に答える