alfredjunkyardgreen has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I have a push to an array that I need to figure out
push @{$labels{$tablename}}, $_;
would someone walk me thru that?
$labels{$tablename}will be the scalar produced from "looking up" $tablenamein %labelsright? but %labelsat the time of invocation has been set to () by
%labels = (); #so push @{non-existent value for $tablename}, $_;
arrgh. grok error! :) Please help. thanks!

Replies are listed 'Best First'.
Re: Figuring out some data structure
by Corion (Patriarch) on Nov 01, 2009 at 15:08 UTC

    From what you show us, this interpretation sounds correct. Maybe you want to take a closer look at what's currently in %labels by using Data::Dumper:

    print Dumper \%labels;

    Also, if you have use strict; at the top of your program (or in the relevant block), that will prevent such bad things as using a string where a reference is expected. If you don't have it, now is a good time to start with the innermost block you're changing and putting use strict; there, just to catch such things.

Re: Figuring out some data structure
by gmargo (Hermit) on Nov 01, 2009 at 16:11 UTC

    What's happening is "autovivification" of an array reference.

    A quote from the book:
    Programming Perl, 3rd Ed., p.251
    Chapter 8: References
    "Implicit Creation of References"

    References of an appropriate type simply spring into existence if you dereference them in an lvalue context that assumes they exist.

    So your statement:

    push @{$labels{$tablename}}, $_;
    is the same as:
    $labels{$tablename} = [] if !exists $labels{$tablename}; push @{$labels{$tablename}}, $_;
    See also autovivification in the glossary, and perlref.

      Small nit: It's more like

      $labels{$tablename} = [] if !defined $labels{$tablename}; push @{$labels{$tablename}}, $_;

        I stand corrected.
        If the $labels{$tablename} already exists but has an undefined value, then that "undef" is replaced with a reference to new anonymous array. I wish this was documented better.

Re: Figuring out some data structure
by AnomalousMonk (Archbishop) on Nov 01, 2009 at 17:29 UTC
    A small point further to the excellent replies of Corion and gmargo:

    While the OP defines the state of the  %labels hash, it does not say if  $tablename is initialized or not; the signs and symptoms will differ in the two cases (assuming warnings and strictures are used – as they always should be!).

    If  $tablename is undefined, it will be 'coerced' to the empty string, which is a valid hash key.

    >perl -wMstrict -le "my %labels; my $tablename; $_ = 'foo'; push @{ $labels{$tablename} }, $_; use Data::Dumper; print Dumper \%labels; " Use of uninitialized value $tablename in hash element at .... $VAR1 = { '' => [ 'foo' ] }; >perl -wMstrict -le "my %labels; my $tablename = 'bar'; $_ = 'foo'; push @{ $labels{$tablename} }, $_; use Data::Dumper; print Dumper \%labels; " $VAR1 = { 'bar' => [ 'foo' ] };
Re: Figuring out some data structure
by planetscape (Chancellor) on Nov 01, 2009 at 18:17 UTC
      Thanks everyone for your replies, esp gmargo. That really clarified the issue. @AnomalousMonk, no $tablename was intialized so that is one thing I didn't have to fight with. :)
Re: Figuring out some data structure
by biohisham (Priest) on Nov 01, 2009 at 17:46 UTC
    There are many ways to create a hash, and %labels = () is correct, since it creates an empty hash or could have been used to make %labels empty all over again. In the context you presented here, "$labels{$tablename}" would be an array reference whose value is the type of the reference and its location, something like ARRAY(0x229c4c).

    Since it is a reference it required appropriate dereferencing to be treated as an array so you can push and pop and do all sorts of array operations on it. This is why @{} is used, it dereferences an array reference.

    So after all, $labels{$tablename} is a scalar that holds a reference to an anonymous array whose values are the table-names.


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.