Why do I need to touch Hash if assigned via map?

Viewed 65

When I do this it works (these are the last 4 lines before the end of a method TWEAK. However, my first attempt had no line #3 and failed because %!columns was empty...

    constant @alphi = 'A'..Inf;

    1 if ! %!columns {
    2     @alphi[0..^@!data.first.elems].map( {%!columns{$_} = $++} );
    3     %!columns  #<== have to "touch" %!columns to avoid empty hash
    4 }  

I am cool that the issue is fixed by "touching" the attribute ... but seems like magic ... can anyone explain why?

1 Answers

Without the %!columns on line three, the call to map is lazy and thus never gets evaluated (the %!columns call wants to check the current value of columns, which implies eagerness).

To more explicitly invoke eagerness, either use the eager statement prefix (shown below) or switch to a for loop, which is eager by default.

I think this code will behave the way you want it to:

if ! %!columns {
   eager @alphi[0..^@!data.first.elems].map( {%!columns{$_} = $++} );
}  
Related