В чем разница между моим и местным в Perl? - PullRequest
59 голосов
/ 25 сентября 2008

Я вижу, как они оба используются в этом сценарии, который я пытаюсь отладить, и литература просто не ясна Может кто-нибудь объяснить мне это?

Ответы [ 14 ]

52 голосов
/ 25 сентября 2008

Краткий ответ: my помечает переменную как частную в лексической области, а local помечает переменную как частную в динамической области.

Проще понять my, так как это создает локальную переменную в обычном смысле. Создана новая переменная, и она доступна только внутри заключительного лексического блока, который обычно отмечается фигурными скобками. Есть несколько исключений из правила фигурных скобок, таких как:

foreach my $x (@foo) { print "$x\n"; }

Но это всего лишь Perl, который делает то, что вы имеете в виду. Обычно у вас есть что-то вроде этого:

sub Foo {
   my $x = shift;

   print "$x\n";
}

В этом случае $x является частным для подпрограммы, и ее область действия заключена в фигурные скобки. Следует отметить, что в отличие от local, область действия переменной my определяется по отношению к вашему коду, как он написан в файле. Это феномен времени компиляции.

Чтобы понять local, вам нужно думать о стеке вызовов вашей программы во время ее работы. Когда переменная local, она переопределяется с точки, в которой оператор local выполняется для всего, что находится ниже стека, до тех пор, пока вы не вернете обратно стек в вызывающую сторону блока, содержащего local.

Поначалу это может сбить с толку, поэтому рассмотрим следующий пример.

sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }

$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect

Когда foo вызывается в первый раз, он видит глобальное значение $x, которое равно 1. Когда вызывается bar и выполняется local $x, это переопределяет глобальное $x в стеке. Теперь, когда foo вызывается из bar, он видит новое значение 2 для $x. Пока что это не очень особенное, потому что то же самое произошло бы без вызова local. Волшебство в том, что когда bar возвращается, мы выходим из динамической области, созданной local $x, и предыдущий глобальный $x возвращается в область. Таким образом, для последнего вызова foo, $x равно 1.

Вы почти всегда захотите использовать my, так как это даст вам локальную переменную, которую вы ищете. Однажды в голубой луне, local действительно удобно делать крутые вещи.

35 голосов
/ 25 сентября 2008

Динамическое определение объема. Это аккуратная концепция. Многие люди не используют его или не понимают.

В основном my считают созданием и привязкой переменной к одному блоку {}, A.K.A. Объем.

my $foo if (true); # $foo lives and dies within the if statement.

Итак, переменная my - это то, к чему вы привыкли. тогда как с динамической областью видимости $ var может быть объявлен где угодно и использоваться где угодно. Так что с local вы в основном приостанавливаете использование этой глобальной переменной и используете «локальное значение» для работы с ней. Таким образом, local создает временную область для временной переменной.

$var = 4;
print $var, "\n";
&hello;
print $var, "\n";

# subroutines
sub hello {
     local $var = 10;
     print $var, "\n";
     &gogo; # calling subroutine gogo
     print $var, "\n";
}
sub gogo {
     $var ++;
}

Это должно вывести:

4
10
11
4
18 голосов
/ 25 сентября 2008

Цитирование из Изучение Perl :

Но местный назван неправильно или, по крайней мере, неверно назван. Наш друг Чип Зальценберг говорит, что если он когда-либо получит возможность вернуться в машину времени к 1986 году и дать Ларри один совет, он скажет Ларри позвонить местному населению под именем «сохранить». [14] Это связано с тем, что local на самом деле сохранит значение данной глобальной переменной, поэтому позже она будет автоматически восстановлена ​​в глобальной переменной. (Это верно: эти так называемые «локальные» переменные на самом деле являются глобальными!) Этот механизм сохранения и восстановления тот же, который мы уже видели дважды, в управляющей переменной цикла foreach и в @_ массив параметров подпрограммы.

Таким образом, local сохраняет текущее значение глобальной переменной, а затем задает для нее некоторую форму пустого значения. Вы часто будете видеть, что он используется для удаления всего файла, а не для начала строки:

my $file_content;
{
    local $/;
    open IN, "foo.txt";
    $file_content = <IN>;
} 

Вызов local $/ устанавливает разделитель входной записи (значение, при котором Perl прекращает чтение «строки») в пустое значение, в результате чего оператор космического корабля читает весь файл, поэтому он никогда не попадает в разделитель входной записи.

16 голосов
/ 26 сентября 2008

Не могу поверить, что никто не связался с исчерпывающими трактатами Марка Джейсона Доминуса по этому вопросу:

9 голосов
/ 25 сентября 2008

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()

В отличие от динамических переменных, созданных локальный оператор, лексические переменные объявлено с моей полностью скрыты из внешнего мира, в том числе любой называется подпрограммы. Это правда, если это та же подпрограмма, вызванная из сам или в другом месте - каждый звонок получает его собственная копия.

http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()

Локальный изменяет свои перечисленные переменные быть "локальным" для вмещающего блока, Eval или сделать файл - и к любому подпрограмма вызывается изнутри, что блок. Местный житель даёт временный значения глобальные (имеется в виду пакет) переменные. Это не создает локальный переменная. Это известно как динамический обзорное. Лексический обзор сделан с мой, который работает больше как авто C деклараций.

Я не думаю, что это вообще неясно, за исключением того, что "локально по отношению к включающему блоку" это означает, что первоначальное значение восстанавливается при выходе из блока.

7 голосов
/ 25 сентября 2008

Ну, Google действительно работает для вас на этом: http://www.perlmonks.org/?node_id=94007

Из ссылки:

Краткое резюме: «my» создает новый переменная, 'local' временно исправляет значение переменной.

т.е. 'local' временно изменяет значение переменной , но только в рамках существует в.

Как правило, используйте мой, он быстрее и не делает ничего странного.

6 голосов
/ 25 сентября 2008

С man perlsub:

В отличие от динамических переменных, созданных локальным оператором, лексические переменные, объявленные с помощью my, полностью скрыты от внешнего мира, включая любые вызываемые подпрограммы. Итак, упрощенно, my делает вашу переменную видимой только там, где она объявлена. local делает его видимым и в стеке вызовов. Обычно вы хотите использовать my вместо local.

4 голосов
/ 25 сентября 2008

Ваша путаница понятна. Лексическое определение довольно легко понять, но динамическое определение - необычное понятие. Ситуация усугубляется тем, что имена my и local несколько неточны (или, по крайней мере, не интуитивны) по историческим причинам.

my объявляет лексическую переменную - видимую от точки объявления до конца включающего блока (или файла). Он полностью независим от любых других переменных с таким же именем в остальной части программы. Это личное сообщение для этого блока.

local, с другой стороны, объявляет временное изменение значения глобальной переменной. Изменение заканчивается в конце охватывающей области, но переменная, будучи глобальной, видна в любом месте программы.

Как правило, используйте my для объявления собственных переменных и local для контроля воздействия изменений встроенных переменных Perl.

Более подробное описание см. В статье Марка Джейсона Домина Как справиться со Scoping .

3 голосов
/ 25 сентября 2008

local - более старый метод локализации, со времен, когда Perl имел только динамическую область видимости. Лексическая область видимости намного более естественна для программиста и намного безопаснее во многих ситуациях. мои переменные принадлежат области (блок, пакет или файл), в которой они объявлены.

Вместо этого

локальные переменные фактически принадлежат глобальному пространству имен. Если вы ссылаетесь на переменную $ x с помощью local, вы на самом деле ссылаетесь на $ main :: x, который является глобальной переменной. Вопреки тому, что подразумевается под его именем, все локальное делает это помещать новое значение в стек значений для $ main :: x до конца этого блока, после чего старое значение будет восстановлено. Это полезная функция сама по себе, но это не очень хороший способ иметь локальные переменные по множеству причин (подумайте, что происходит, когда у вас есть потоки! И подумайте, что произойдет, когда вы вызываете процедуру, которая действительно хочет использовать глобальную Вы локализовали!). Однако это был единственный способ получить переменные, которые выглядели как локальные переменные в старые добрые времена до Perl 5. Мы все еще застряли с этим.

2 голосов
/ 10 апреля 2013

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

our $name = "Abhishek";

sub sub1
{
    print "\nName = $name\n";
    local $name = "Abhijeet";

    &sub2;
    &sub3;
}

sub sub2
{
    print "\nName = $name\n";
}

sub sub3
{
    my $name = "Abhinav";
    print "\nName = $name\n";
}


&sub1;

Вывод:

Name = Abhishek

Name = Abhijeet

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