Global symbol requires explicit package name это типичная, и, на мой взгляд, весьма вводящее в заблуждение сообщение об ошибке в Perl. Во всяком случае, для новичков.
Простой перевод - "Надо объявить переменную с помощью my."
Простейший пример
use strict;
use warnings;
$x = 42;
И ошибка
Global symbol "$x" requires explicit package name at ...
(Глобальный символ "$x" требует явного имени модуля на строке...)
Хотя само по себе сообщение об ошибке корректно, от этого мало толку для новичка в Perl-программировании. Он, возможно, даже не знает, что такое модули. И также ему непонятно, что может быть более явно, чем $x.
Это ошибка генерируется из-за use strict.
Вот объяснение из документации:
Это выражение генерирует ошибку компиляции, если вы обращаетесь к переменной, которая не была объявлена с помощью "our" или "use vars", локально объвлена с помощью "my()", или не была полностью определена.Стоит надеяться, что новичок будет начинает каждый свой скрипт с use strict, и наверняка узнает о my гораздо раньше, чем о других вариантах.
Я не знаю, возможно и следует ли изменить этот текст в perl'е. Цель этой статьи не в этом. Цель в том, чтобы помочь новичкам понять для себя, что значит это сообщение об ошибке.
Чтобы избавиться от этого сообщение об ошибке, нужно написать:
use strict;
use warnings;
my $x = 42;
То есть, нужно объявить переменную с помощью my, прежде чем использовать ее в первый раз. That is, one needs to declare the variable using my before its first use..
Плохое решение
Другое "решение" - убрать strict:
#use strict;
use warnings;
$x = 23;
это сработает, но выдаст предупреждение Name "main::x" used only once: possible typo at ....
Так или иначе, в нормальной ситуации вы не станете вести машину, не пристегнувшись, не так ли?
Пример 2: область видимости
Другой случай, часто наблюдаемый у новичков:
use strict;
use warnings;
my $x = 1;
if ($x) {
my $y = 2;
}
print $y;
Здесь мы получим ту же ошибку, что и в предыдущем примере:
Global symbol "$y" requires explicit package name at ...
что для многих удивительно. Особенно, когда они начинают программировать. В конце концов, они же
объявили $y
с помощью my
.
Для начала, здесь есть небольшая визуальная проблема. Нет отступа перед my $y = 2;
.
Если бы мы сделали отступ в пару пробелов или табуляцию, как в следующем примере, источник проблемы
мог бы стать более очевидным:
use strict;
use warnings;
my $x = 1;
if ($x) {
my $y = 2;
}
print $y;
Проблема в том, что переменная $y
объявлена внутри блока(между фигурными скобками),
а это значит, что вне пределов блока она не существует. Это называется
областью видимости переменной.
Сама идея областей видимости отличается в разных языках программирования. В Perl блок,
ограниченный фигурными скобками, создает область видимости. То, что объявлено внутри нее с
помощью my
, не будет доступно за границами блока.
(К слову, выражение $x = 1
здесь добавлено только чтобы создать правдоподобное условие
для создания блока. Другими словами, условие if ($x) {
нужно здесь, чтобы сделать пример
более реальным.)
Решение здесь - либо вызвать print
внутри блока:
use strict;
use warnings;
my $x = 1;
if ($x) {
my $y = 2;
print $y;
}
либо объявить переменную за границами блока (а не внутри!):
use strict;
use warnings;
my $x = 1;
my $y;
if ($x) {
$y = 2;
}
print $y;
Какой способ выбрать, зависит уже от конкретной задачи. Это лишь синтаксически допустимые решения.
Конечно, если мы забудем убрать my
из блока, или если $x
будет FALSE, то мы
получим предупреждение Use of uninitialized value.
Другие способы
Объяснение того, что делают выражения our
и use vars
, или как можно полностью
определить имя переменной, мы оставим для другой статьи.