Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Замыкание и изменение лексической переменной


Автор: MaXL 20.8.2010, 20:49
Всем привет. Изучаю Perl, дошёл до замыканий и кое-чего не понял. Думаю кто-нибудь поможет прояснить ситуацию.
Написал небольшой скрипт, использующий замыкания:
Код

use warnings;
use strict;

sub genFunc
{
  my $k = shift;
  my $newF = sub
  {
    my $x = shift;
    return $k * $x;
  };
  return $newF;
}

$a = genFunc(10);
$b = genFunc(20);

print $a->(11), "\n";
print $b->(11);

он, как и ожидалось выводит
110
220
После чего, исправил функцию genFunc следующим образом:
Код

use warnings;
use strict;

sub genFunc
{
  my $k = shift;
  my $newF = sub
  {
    my $x = shift;
    return $k * $x;
  };
  $k = 10;
  return $newF;
}

$a = genFunc(10);
$b = genFunc(20);

print $a->(11), "\n";
print $b->(11);

и получил неожиданный, для себя результат:
110
110
Не могу никак понять, из-за чего появляется такой эффект. Ведь изменил я значение переменной $k уже после определения функции, на которую ссылается $newF  smile 
У нас уже конешно  пять утра, но всё же smile

Автор: dva300 21.8.2010, 10:02
работа функции начинается в моент ее вызова. 
замыкание - возврат ссылки на функцию.
вызов $a->(11)
но перед этим копия лексических переменных уже сохроненна с измененным значением переменной $x.

Автор: Pfailed 21.8.2010, 10:07
$k внутри анонимной подпрограммы ссылается на $k внутри подпрограммы genFunc. Соответственно при вызове анонимной функции это самое $k равно значению  $k внутри genFunc.

Автор: MaXL 21.8.2010, 12:30
dva300, Pfailed,  спасибо. Значит такое поведение действительно является правильным.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)