Global symbol requires explicit package name

strict my package global symbol

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, или как можно полностью определить имя переменной, мы оставим для другой статьи.

Otras páginas

Учебник Perl по-русски
Автоматический перевод строк в числа или приведение типов в Perl
Name 'main::x' used only once: possible typo at ...
Name 'main::x' used only once: possible typo at ...
'my' variable masks earlier declaration in same scope

Author

Gabor Szabo (szabgab) Gabor Szabo