Question

Actually I found a weird behavior when i try to initialize a Perl Hash(ref) and try to assign it via autovivication at once. Here is a short Codesnippet to make it a bit clearer:

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

That prints:

$VAR1 = undef;

When i try it that way:

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

i get

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

Which is what i expected. So the Problem is the (multiple) initialzing of $hash.

I know, that the way of using map is a better solution here:

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

Now my Question: Why does the way of initialzing and assigning at once fail?

Was it helpful?

Solution

Read the note near the end of the Statement Modifiers section of the perlsyn - Perl Syntax:

NOTE: The behaviour of a my, state, or our modified with a statement modifier conditional or loop construct (for example, my $x if ... ) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.

OTHER TIPS

Would you expect this to work?

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

PBP says that you should not use any statement modifier except if and then only to modify a last, next or redo.

If you compare the following two outputs it should be easy to see why you don't have anything in $hash. There is no padsv before the loop, so the loop gets its own variable of the same name ( same index in the pad ).
Which means you actually have 2 or 5 variables named $hash. ( I'm not sure if the loop maintains the same variable or if it gets a new one each time through. )

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] # <-----
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top