Search code examples
perlstrict

Perl Global symbol requires explicit package name


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.


Solution

  • 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{...} ...