5

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.

ikegami
  • 367,544
  • 15
  • 269
  • 518
i01000001
  • 119
  • 1
  • 2
  • 9

2 Answers2

10
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{...} ...
    
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    Thanks for such a detailed response. I did know about this scalar and non-scalar variables concept in declaration. I appreciate you brought this out! – i01000001 May 01 '13 at 18:13
  • Then for completeness: `my %log;` declares a hash, `my @log;` declares an array, and `my $log`; declares a scalar. These are three unrelated variables which can safely co-exist (readability issues aside). – ikegami May 01 '13 at 18:16
  • this is one responsive community.. never seen this anywhere else.. or may be I was looking at wrong places.. anyway I have taken the second option you proposed.. and took note on scalars and non-scalars! thanks again. – i01000001 May 01 '13 at 18:36
9

I'm not sure what are you trying to do with $1, but the hash access is not a reference, so change:

$log->{$1}

to

$log{$1}

The error message you got, says: Global symbol "$log" requires explicit package, because $log variable was not defined. Remember that %log and $log are two different variables (hash vs scalar).

Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99
Miguel Prz
  • 13,718
  • 29
  • 42
  • 1
    Thanks for your response. I am not being given an option to accept both replies as correct answer to my question. Don't know how to acknowledge your effort... May be if I can share some reputation points.. dont the rules here.. I just joined today! – i01000001 May 01 '13 at 18:15