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

Hi, I have the following 2 code snippets which in my opinion are supposed to do the same thing. Snippet 1 works fine, but snippet 2 doesn't even compile. It emits 'requires explicit package name' error on line 2. @libs is an array of hashes. Thanks for any help. daniel
1 for (my $i = 0; $i < @libs; $i++) { 2 my $file = $libs[$i]{'file'}; 3 print "reading $file\n"; 4 } 1 foreach my $lib (@libs) { 2 my $file = $lib{'file'}; 3 print "reading $file\n"; 4 }

Replies are listed 'Best First'.
Re: foreach problem
by Fletch (Bishop) on Mar 03, 2009 at 19:21 UTC

    That's because in line two you're referring to using the package variable %lib when you mean to be dereferencing the hashref you've got: $lib->{'foo'}.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: foreach problem
by kennethk (Abbot) on Mar 03, 2009 at 19:23 UTC
    A reread through perllol or perlreftut might be helpful. When you use the syntax $libs[$i]{'file'} it's actually short hand for $libs[$i]->{'file'} since each element of @libs is a hash reference. The error 'requires explicit package name' is because $lib{'file'} is trying to access the 'file' element of the hash %lib - the dereference cannot be done automatically due to potential syntactic ambiguity. What would work for you is:

    1 foreach my $lib (@libs) { 2 my $file = $lib->{'file'}; 3 print "reading $file\n"; 4 }

Re: foreach problem
by ikegami (Patriarch) on Mar 03, 2009 at 20:06 UTC

    Keep in mind an array of hashes is actually an array of references to hashes.

    $libs[$i]{'file'}

    is shorthand for

    $libs[$i]->{'file'}

    so if you replace array element $libs[$i] with scalar $lib, you get

    $lib->{'file'}

    $lib{'file'} refers to the hash %lib.

Re: foreach problem
by zwon (Abbot) on Mar 03, 2009 at 19:23 UTC

    $lib->{'file'} should work

Re: foreach problem
by glasswalk3r (Friar) on Mar 03, 2009 at 19:25 UTC

    Enabling:

    use warnings; use strict;

    Should do it. This is very basic and you should be using it always.

    Alceu Rodrigues de Freitas Junior
    ---------------------------------
    "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

      Do what pray? The following code (without strictures)

      my @libs = qw{1 2 3 4}; foreach my $lib (@libs) { my $file = $lib{'file'}; print "reading $file\n"; }

      Prints:

      reading reading reading reading

      and with use strict added generates the error:

      Global symbol "%lib" requires explicit package name at ... line 7. Execution of ... aborted due to compilation errors.

      which is the 'requires explicit package name' that worried the OP (and quite rightly). The OP is using strictures and they have just saved his job/his marriage/his sanity/the world, or whatever. Good OP++!


      True laziness is hard work