Когда глобальная переменная получает свое значение? - PullRequest
2 голосов
/ 04 августа 2010

Я столкнулся с некоторым странным поведением, которое намекает на то, что я не понимаю некоторые основные вещи о выполнении сценариев Perl и порядке инициализации. Следующий пример:

#!/usr/bin/env perl

use strict;
use warnings;

print &get_keys(), "\n";

use vars qw/%hello/;  # same effect with 'my %hello = (...);'
%hello = ( a => 1, b => 2 );

sub get_keys
{
        return join(', ', sort keys %hello);
}

печатает пустую строку. Это означает, что хотя переменная уже видна, поскольку состояние с присваиванием еще не достигнуто, оно не имеет значения. (Использование скаляра вместо хеша вызовет предупреждение о неинициализированной переменной.)

Это предполагаемое поведение?

Я был бы также рад за указатели RTFM.

Ответы [ 3 ]

8 голосов
/ 04 августа 2010

С perlsub :

A my имеет эффект как времени компиляции, так и времени выполнения.Во время компиляции компилятор обращает на это внимание.Основная полезность этого заключается в том, чтобы успокоить use strict 'vars' .... Фактическая инициализация откладывается до времени выполнения, поэтому она выполняется в соответствующее время.

# At this point, %hello is a lexically scope variable (the my took effect
# at compile time), but it still has no keys.
print get_keys();

my %hello = ( a => 1, b => 2 );

# Now the hash has content.
print get_keys();

sub get_keys { join ' ', keys %hello, "\n" }

Другие примечания: (1) Вы должны использовать my или our вместо use vars.(2) В обычных условиях не вызывайте функции с начальным амперсандом: используйте foo() вместо &foo().

4 голосов
/ 04 августа 2010

Да, это предполагаемое поведение.Вы набираете get_keys(), прежде чем назначить %hello, поэтому %hello пусто в get_keys().(Скаляры инициализируются на undef, а массивы и хэши по умолчанию устанавливаются пустыми.)

Если вы хотите, чтобы %hello был немедленно инициализирован, используйте блок BEGIN:

use vars qw/%hello/;
BEGIN {
    %hello = ( a => 1, b => 2 );
}

Обратите внимание, что если вы используете my (или our, в этом отношении), то это не будет работать:

BEGIN {
    my %hello = ( a => 1, b => 2 );
}

, потому что вы должны объявить переменную вне блока, напримеритак:

my %hello;
BEGIN {
    %hello = ( a => 1, b => 2 );
}
3 голосов
/ 04 августа 2010

Прагма use vars предопределяет имя глобальной переменной во время компиляции. Переменная не определена, если вы не назначите ей какое-либо значение. Поскольку вы распечатываете его перед назначением, вы по праву получаете пустую строку.

Кстати, эта прагма устарела. От perldoc vars :

ПРИМЕЧАНИЕ. Для переменных в текущем пакете предусмотрены функции эта прагма была заменена "нашими" декларациями, доступными в Perl v5.6.0 или новее Смотрите "наш" в perlfunc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...