Как сказал yi_H, my $g
, который вы объявляете внутри цикла, является полностью отдельной переменной от $g
, который используется recurse
.Это работает в первый раз, потому что все переменные начинаются с undef
, который в виде строки становится пустой строкой.Если вы попытаетесь распечатать $g
внутри цикла после вызова recurse
, вы увидите, что он все еще пуст.Использование строгого помогает выявить ошибки такого рода.Он может или не может поймать этот случай, в зависимости от того, как выглядит остальная часть вашей программы.
Самый простой способ справиться с этим - передать $g
в качестве параметра.Однако иногда проще использовать рекурсивное замыкание.Обратите внимание, что Perl использует сборщик мусора с подсчетом ссылок, что означает, что он не может удалять структуры самоссылочных данных (включая замыкание, которое имеет ссылку на себя, чтобы он мог вызывать себя рекурсивно) до завершения всей программы.Я использую функцию ослабления из Scalar :: Util , чтобы избежать этого.$strongRef
используется только для того, чтобы предотвратить сбор мусора перед тем, как мы закончим с ним.
use Scalar::Util 'weaken';
for (my $i = 0; $i < 3; $i++)
{
my $g = '';
my $recurse;
my $strongRef = $recurse = sub {
my $m = shift;
$g .= "::" . $m;
if ($m == 0) { return $g; }
else { $m--; $recurse->($m); }
};
weaken($recurse); # Prevent memory leak
my $str = $recurse->(10);
print $str . "\n";
}
Однако, в данном конкретном случае, я бы просто заполнил замыкание $str
непосредственно вместо возврата значения:
for (my $i = 0; $i < 3; $i++)
{
my $str = '';
my $recurse;
my $strongRef = $recurse = sub {
my $m = shift;
$str .= "::" . $m;
if ($m-- > 0) { $recurse->($m); }
};
weaken($recurse); # Prevent memory leak
$recurse->(10);
print $str . "\n";
}