Perl Global symbol requires explicit package name

i01000001 picture i01000001 · May 1, 2013 · Viewed 10.5k times · Source

I am trying to store my log messages in a hash depending upon message type as shown below:

#!/usr/bin/perl

use strict;
use warnings;

my %log;

opendir (DIR, '.') or die $!;
while (my $file = readdir(DIR)) {
    # some code to select TAR filename in $1
    if (-e $1.'.tar') {
        push(@{$log->{$1}}, $file); /* line 12 */
    }
    else {
        $log{$1} = [];
        push(@{$log->{$1}}, $file); /* line 16 */
}

Now this code gives compilation error saying:

Global symbol "$log" requires explicit package name at at lines 12 & 16

where I am actually trying to use the hash "%log". What can be a possible way to get rid of this error ? Why exactly is this happening ?

I did see some explanation on context where people replied saying the variables were created in one context and were being referred in another but I feel this variable should be available inside while loop in this piece of code. This happens only when I have "use strict" and works fine otherwise.

I have started with Perl so I do not fully understand the basics! Please help me understand why this variable is not accessible.

Answer

ikegami picture ikegami · May 1, 2013
my %log;

defines hash %log, but lines 12 and 16 don't use it. Instead, you're accessing the anonymous hash referenced by the scalar $log which you've never declared. You have two options.

  • You could continue to use an anonymous hash.

    my $log = {};   # The creation of the hash ("{}") is currently being done
                    # implicitly by "->". This is called autovivification.
    
    
    ... $log->{...} ...
    

    This adds a bit of a extra complexity and an unnoticeable reduction in speed.

  • You could use use a hash directly.

    my %log;
    
    ... $log{...} ...