1

实际上,当我尝试初始化 Perl Hash(ref) 并尝试立即通过autovivication分配它时,我发现了一个奇怪的行为。这是一个简短的代码片段,使其更清晰:

use Data::Dumper;
my $hash->{$_} = 'abc' foreach (1..4);
print Dumper $hash;

打印:

$VAR1 = undef;

当我这样尝试时:

use Data::Dumper;
my $hash;
$hash->{$_} = 'abc' foreach (1..4);
print Dumper $hash;

我明白了

$VAR1 = {
          '4' => 'abc',
          '1' => 'abc',
          '3' => 'abc',
          '2' => 'abc'
        };

这是我所期望的。所以问题是 的(多个)初始化$hash

我知道,map这里的使用方式是一个更好的解决方案:

use Data::Dumper;
my $hash = { map { $_ => 'abc' } (1..4) };
print Dumper $hash;

现在我的问题:为什么一次初始化和分配的方式会失败?

4

3 回答 3

8

阅读perlsyn - Perl Syntax的Statement Modifiers部分末尾附近的注释:

注意:使用语句修饰符条件或循环构造(例如,my $x if ...)修改的 my、state 或 our 的行为是未定义的。my 变量的值可以是 undef、任何先前分配的值,或者可能是其他任何值。不要依赖它。未来版本的 perl 可能会做一些与您尝试使用的 perl 版本不同的事情。这里是龙。

于 2013-08-05T12:13:57.217 回答
1

你会期望这行得通吗?

foreach ( 1 .. 4 ){
    my $hash->{$_} = 'abc';
}

PBP 说你不应该使用任何语句修饰符,除了然后if只修改 a或。lastnextredo

于 2013-08-05T14:50:54.017 回答
0

如果您比较以下两个输出,应该很容易看出为什么您在$hash. 循环之前没有padsv,因此循环获取自己的同名变量( pad 中的相同索引)。
这意味着您实际上有2 或 5 个名为$hash. (我不确定循环是否保持相同的变量,或者每次都获得一个新变量。)

perl -MO=Terse -e'my $hash->{$_} = "abc" for 1..4;print $hash'
LISTOP (0x1e7ff90) leave [1] 
    OP (0x1f8ace0) enter 
    COP (0x1e35e60) nextstate 
    BINOP (0x1e34aa0) leaveloop 
        LOOP (0x1e35dc0) enteriter 
            OP (0x1e35bd0) null [3] 
            UNOP (0x1e36050) null [146] 
                OP (0x1e27870) pushmark 
                SVOP (0x1e35c90) const [7] IV (0x1e2da60) 1 
                SVOP (0x1e35c20) const [8] IV (0x1e2dad8) 4 
            PADOP (0x1e89160) gv  GV (0x1e0e7c0) *_ 
        UNOP (0x1e35cd0) null 
            LOGOP (0x1e35f00) and 
                OP (0x1e35d90) iter 
                LISTOP (0x1e34960) lineseq 
                    BINOP (0x1e34a00) sassign 
                        SVOP (0x1e34a60) const [9] PV (0x1e2db68) "abc" 
                        BINOP (0x1e35d10) helem 
                            UNOP (0x1e35d50) rv2hv [3] 
                                OP (0x1e34930) padsv [1] # <-----
                            UNOP (0x1e35e20) null [15] 
                                PADOP (0x1e35fe0) gvsv  GV (0x1e0e7c0) *_ 
                    OP (0x1fa9ad0) unstack 
    COP (0x1e26830) nextstate 
    LISTOP (0x1fb8e30) print 
        OP (0x1fa9a10) pushmark 
        OP (0x1e26800) padsv [1] # <-----
perl -MO=Terse -e'my $hash;$hash->{$_} = "abc" for 1..4;print $hash'
LISTOP (0xb33fe0) leave [1] 
    OP (0xc88c00) enter 
    COP (0xb32a40) nextstate 
    OP (0xb32930) padsv [1] # <-----
    COP (0xb33f40) nextstate 
    BINOP (0xb33cd0) leaveloop 
        LOOP (0xb33e60) enteriter 
            OP (0xb33d90) null [3] 
            UNOP (0xb87160) null [146] 
                OP (0xb25870) pushmark 
                SVOP (0xb33c20) const [7] IV (0xb2ba60) 1 
                SVOP (0xb32aa0) const [8] IV (0xb2bad8) 4 
            PADOP (0xb7df90) gv  GV (0xb0c7c0) *_ 
        UNOP (0xb33f00) null 
            LOGOP (0xb32960) and 
                OP (0xca7ad0) iter 
                LISTOP (0xb34050) lineseq 
                    BINOP (0xb33c90) sassign 
                        SVOP (0xb33de0) const [9] PV (0xb2bb68) "abc" 
                        BINOP (0xb32a00) helem 
                            UNOP (0xb33d10) rv2hv [3] 
                                OP (0xb33bd0) padsv [1] # <-----
                            UNOP (0xb33d50) null [15] 
                                PADOP (0xb33e20) gvsv  GV (0xb0c7c0) *_ 
                    OP (0xca7aa0) unstack 
    COP (0xb24830) nextstate 
    LISTOP (0xcb6e30) print 
        OP (0xc88ce0) pushmark 
        OP (0xb24800) padsv [1] # <-----
于 2013-08-07T00:46:50.000 回答