|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : Andrey Sapozhnikov 2:5020/400 04 Nov 2004 19:09:55 To : Artem Chuprina Subject : Re: А есть ли в эхотаге рекурсия? --------------------------------------------------------------------------------
Artem Chuprina пишет:
> Alexander Pashchenko -> Artem Chuprina @ Tue, 02 Nov 2004 22:38:00 +0300:
>
> AC>> В современных перлах можно сказать open(my $f, ...). Будет работать
> AP> А "современные перлы" это какие версии?
>
> Hачиная с 5.6.
>
> AC>> Даже close не потребуется.
> AP> Хорошая привычка закрывать файлы :) Да и переменные отдельным
> AP> блоком объявлять.
> AP>>> Кстати, а большая ли разница между my и local?
> AC>> Принципиальная.
> AP> Да я понимаю, что принципиальная. Что-то связанное с видимостью: вроде
> AP> как local - текущий блок и ниже, а my - только текущий блок. Так?
>
> Гораздо хуже. Лучше, конечно, почитать в какой-нибудь умной книжке.
> Hо. my-переменная видна только в этом блоке _и в определенных в нем
> функциях_ (это отдельная довольно сложная для человека, задающего
> подобные вопросы, тема), зато время жизнии ее значения не ограничено.
> local - это глобальная переменная, которая имеет указанное значение на
> время выполнения данного блока. Т.е. она видна всегда, а ее данное
> значение живет до выхода из этого блока, потом замещается внешним (для
> случая рекурсии - там стек значений).
Hу не совсем все так. Значение локальной переменной, как и любой другой,
живет до тех пор пока не пропадет последняя ссылка на него. С выходом из
блока исчезает локальная таблица имен для данного блока, и разыменование
производится по локальным таблицам более "вышестоящего" уровня (для
вложенных блоков) и глобальной таблице имен.
================= пример =======================
#!/usr/bin/perl -w
use strict;
our $v = 'global';
our $vref;
sub so { print "test $_[0]: $v\n"; }
sub sr { print "test $_[0]: $$vref\n"; }
print "test 1: $v\n";
{
local $v = 'local';
print "test 2: $v\n";
sub si { print "test $_[0]: $v\n"; }
$vref = \$v;
so(3);
si(4);
sr(5);
}
so(6);
si(7);
sr(8);
================== вывод =====================
test 1: global
test 2: local
test 3: local
test 4: local
test 5: local
test 6: global
test 7: global
test 8: local
Заметим, что test 8 выводит 'local'. При том, что
вспомогательная переменная $vref никакой строки не
содержит, а содержит лишь ссылку на значение. Выходит,
что значение "живо" и после блока.
Теперь посмотрим на модифицированный пример.
================= пример =======================
#!/usr/bin/perl -w
use strict;
our $v = 'global';
our $vref;
sub so { print "test $_[0]: $v\n"; }
sub sr { print "test $_[0]: $$vref\n"; }
print "test 1: $v\n";
{
my $v = 'local scope';
print "test 2: $v\n";
sub si { print "test $_[0]: $v\n"; }
$vref = \$v;
so(3);
si(4);
sr(5);
}
so(6);
si(7);
sr(8);
================== вывод =====================
test 1: global
test 2: local scope
test 3: global
test 4: local scope
test 5: local scope
test 6: global
test 7: local scope
test 8: local scope
Мы видим, что test 3 теперь выводит глобальную переменную.
Почему? Потому, что переменная типа my не попадает в
локальное пространство имен времени исполнения. Для нее
существует свое пространство имен, разименование по которому
происходит на этапе компиляции (оговорюсь, есть исключения,
но сейчас о них упоминать ни к чему). test 7 теперь выводит
local scope. Почему? Потому, что разименование этой переменной
произошло на этапе компиляции тела функции si. И произошло это
в зоне действия переменной типа my. Ссылка на значение это
переменной была "запомнена" в скомпилированном коде функции
si и функция si теперь печатает ее и только ее. Hесмотря на
то, что "зону видимости" мы давно покинули. test 8 показывает,
как и в прошлом примере, то, что и явные ссылки (а в примере 7
была неявная) указывают на то значение, которое было "видно"
в момент создания этой ссылки. Механизм ссылок таков, что они
указывают не на имя, и не на запись в таблице имен, а на безымянное
по своей природе значение. В данном случае под словом "значение"
понимается не некоторое число/строка/и т.п., а безымянная структура -
область памяти в которой хранится это число/строка/и т.п.. Т.е. если
сразу после строки $vref = \$v; мы впишем $v = 'new value',
то $vref, разумеется, будет указывать на то же "значение", но уже
с новым "содержимым". Эта некоторая путаница с терминологией
исторически сложилась, как результат внутренней организации
переменных в интерпретаторе. Она не такова:
Таблица имен (
Запись в таблице имен 1 = [ИМЯ1, СОДЕРЖИМОЕ1],
Запись в таблице имен 2 = [ИМЯ2, СОДЕРЖИМОЕ2],
Запись в таблице имен 3 = [ИМЯ3, СОДЕРЖИМОЕ3],
...
)
а такова:
Таблица имен (
Запись в таблице имен 1 = [ИМЯ1, ССЫЛКА-HА-ЗHАЧЕHИЕ1],
Запись в таблице имен 2 = [ИМЯ2, ССЫЛКА-HА-ЗHАЧЕHИЕ2],
Запись в таблице имен 3 = [ИМЯ3, ССЫЛКА-HА-ЗHАЧЕHИЕ3],
...
)
Таблица значений (
Значение1 = [счетчик ссылок, СОДЕРЖИМОЕ1],
Значение2 = [счетчик ссылок, СОДЕРЖИМОЕ2],
Значение3 = [счетчик ссылок, СОДЕРЖИМОЕ3],
...
)
конечно все это показано в сильно упрощенном виде. :) Данная
конструкция гораздо более гибка, она например допускает
существование "синонимов" - т.е. когда несколько записей
указывают на одно значение. Допускает существование
безымянных значений (как тех, которые стали безымянными
по причине исчезновения записи в таблице имен при ненулевом
счетчике ссылок, так и изначально безымянных)...
Пока хватит для осмысления? Hа всякий случай перечитайте раза на
три, после чего (если только я достаточно внятно пишу), все окажется
предельно ясным, логичным, простым и единственно разумным настолько,
что будет непонятно как до сих пор можно было во всем этом путаться :-)
To: Artem Chuprina. Хотя этот постинг формально является ответом на
твой (с целью цитирования), адресуется он, раземеется, в первую
очередь новичкам :-)
--
Андрей
--- ifmail v.2.15dev5.3
* Origin: Demos online service (2:5020/400)
Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/65770f68b45f.html, оценка из 5, голосов 10
|