2013-05-01 4 views
3

Я пытаюсь хранить свои журнальные сообщения в хэш в зависимости от типа сообщения, как показано ниже:Perl Global символ требует явного имени пакета

#!/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 */ 
} 

Теперь этот код дает ошибку компиляции, говоря:

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

, где я на самом деле пытаюсь использовать хэш «% log». Каким может быть возможный способ избавиться от этой ошибки? Почему именно это происходит?

Я видел некоторые объяснения в контексте, где люди ответили, что переменные были созданы в одном контексте и передавались в другом, но я чувствую, что эта переменная должна быть доступна внутри цикла while в этом фрагменте кода. Это происходит только тогда, когда я «использую строгую» и в противном случае отлично работает.

Я начал с Perl, поэтому я не полностью понял основы! Пожалуйста, помогите мне понять, почему эта переменная недоступна.

ответ

8
my %log; 

определяет хэш %log, но строки 12 и 16 не использовать его. Вместо этого вы получаете доступ к анонимному хэшу, на который ссылается скаляр $log, который вы никогда не объявляли. У вас есть два варианта.

  • Вы можете продолжать использовать анонимный хеш.

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

    Это добавляет немного дополнительной сложности и незаметного снижения скорости.

  • Вы можете использовать хэш непосредственно.

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

Спасибо за такой подробный ответ. Я знал об этой концепции скалярных и нескалярных переменных в декларации. Я благодарю вас за это! – i01000001

+0

Затем для полноты: 'my% log;' объявляет хэш, 'my @log;' объявляет массив и 'my $ log'; объявляет скаляр. Это три несвязанные переменные, которые могут безопасно сосуществовать (вопросы читаемости в стороне). – ikegami

+0

это одно отзывчивое сообщество .. никогда не видел этого нигде .. или, может быть, я искал неправильные места .. в любом случае я взял второй вариант, который вы предложили .. и принял к сведению скаляры и нескаляры! еще раз спасибо. – i01000001

9

Я не уверен, что вы пытаетесь сделать с $1, но доступ хэш не ссылка, так меняется:

$log->{$1} 

в

$log{$1} 

сообщение об ошибке вы получили , говорит: Global symbol "$log" requires explicit package, потому что переменная $log не определена. Помните, что %log и $log - это две разные переменные (хэш против скаляра).

+1

Спасибо за ваш ответ. Мне не дают возможность принять оба ответа как правильный ответ на мой вопрос. Не знаю, как признать ваши усилия ... Может быть, если я смогу поделиться некоторыми точками репутации .. не правила здесь .. Я только что присоединился сегодня! – i01000001