В Perl существует два основных типа переменных. Один из них - это глобальные переменные модуля,
объявленные либо с помощью ныне устаревшей конструкции use vars
, либо с помощью our
.
Другой тип - это лексические переменные, объявленные с помощью my
.
Давайте посмотрим, что происходит, когда мы объявляем переменную с помощью my
. В каких
местах кода переменная будет доступна? Другими словами, где будет область видимости
переменной?
Область видимости: содержащий блок
#!/usr/bin/perl
use strict;
use warnings;
{
my $email = 'foo@bar.com';
print "$email\n"; # foo@bar.com
}
# print $email;
# $email не существует
# Global symbol "$email" requires explicit package name at ...
Внутри безымянного блока (пара фигурных скобок {}
) мы видим объявление новой переменной
"$email
". Эта переменная существует на участке между ее объявлением и концом блока. Вот
почему строка после закрывающей скобки }
закомментирована. Если убрать #
из строки
# print $email;
и попробовать запустить скрипт, мы получим ошибку компиляции:
Global symbol "$email" requires explicit
package name at ....
Другими словами, область видимости переменной, объявленной с помощью my ограничивается содержащим ее блоком.
Область видимости: видимый везде
Переменная $lname
объявлена в начале кода. Она будет видима везде до конца файла. Даже
внутри блоков. Даже если эти блоки являются объвлениями функций. Если мы изменим переменную внутри
блока, ее значение изменится и в остальном коде. Даже если вы выйдете из блока:
#!/usr/bin/perl
use strict;
use warnings;
my $lname = "Bar";
print "$lname\n"; # Bar
{
print "$lname\n"; # Bar
$lname = "Other";
print "$lname\n"; # Other
}
print "$lname\n"; # Other
Переменная, скрытая другим объявлением
#!/usr/bin/perl
use strict;
use warnings;
my $fname = "Foo";
print "$fname\n"; # Foo
{
print "$fname\n"; # Foo
my $fname = "Other";
print "$fname\n"; # Other
}
print "$fname\n"; # Foo
В этом случае переменная $fname
объвлена в начале кода. Как сказано выше, она будет видима
везде до конца файла, за исключением мест, где она будет "скрыта" локально объявленной переменной
с таким же именем.
Внутри блока мы объявли с помощью my
другую переменную с таким же именем. По сути, это
скроет переменную $fname
, объявленную снаружи блока, пока мы не покинем блок. В конце блока
(}
) переменная $fname
, объявленная внутри него, будет уничтожена, а первоначальная
$fname
снова станет доступна. Эта особенность особенно важна, так как она дает возможность
создавать переменные внутри небольших блоков, не задумываясь о возможном использовании такого же
имени снаружи блока.
Одинаковые имена в разных блоках
Вы можете спокойно использовать одинаковые имена переменных в разных блоках. Эти переменные не будут никак связаны друг с другом.
#!/usr/bin/perl
use strict;
use warnings;
{
my $name = "Foo";
print "$name\n"; # Foo
}
{
my $name = "Other";
print "$name\n"; # Other
}
объявление в модуле внутри файла
Это немного более продвинутый пример, и, возможно, здесь стоит обратить внимание:
Perl позволяет переключаться между пространствами имен внутри одного файла с помощью
ключевого слова package
. Объявление модуля с помощью package
НЕ создает
область видимости. Если вы объявите переменную, явно указав пространство имен с помощью package
main, которое и по умолчанию является телом вашего скрипта, то ваша переменная $fname
все равно будет видима в этом файле, даже в других пространствах имен.
Если вы объявите переменную "$lname
" в пространстве имен "Other", она будет видима, если
потом вы переключитесь обратно на пространство имен main
. Если же объявление package Other
было в другом файле, то переменные, объявленные там, будут находиться в другой области
видимости, созданной файлом.
#!/usr/bin/perl
use strict;
use warnings;
my $fname = "Foo";
print "$fname\n"; # Foo
package Other;
use strict;
use warnings;
print "$fname\n"; # Foo
my $lname = 'Bar';
print "$lname\n"; # Bar
package main;
print "$fname\n"; # Foo
print "$lname\n"; # Bar