1

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?

3 Answers3

8

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.

choroba
  • 231,213
  • 25
  • 204
  • 289
1

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.

shawnhcorey
  • 3,545
  • 1
  • 15
  • 17
  • thats complete not what my problem was... your code works.. you just initialized `$hash` local... –  Aug 05 '13 at 20:12
  • No, I didn't use `local`, I used `my`. My point is that declaring the variable inside the loop does not work. – shawnhcorey Aug 06 '13 at 11:47
  • i dont say that you used `local`. Your `$hash` is just scoped inside the loop. but that was not my problem. –  Aug 06 '13 at 12:06
  • 1
    But that was your problem. Your `my $hash->{$_}` was inside a loop. – shawnhcorey Aug 06 '13 at 12:14
  • nope. It was not inside a loop, it was a loop construct. Thats the difference. and like choroba said, when initiliazing a variable with a loop construct, the value of the may variable may be undef. –  Aug 06 '13 at 12:17
  • But that's the error in your thinking. You think of them as two different things. Until you correct your thinking, you will continue to make errors with all the statement modifiers. – shawnhcorey Aug 06 '13 at 12:20
0

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] # <-----
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129