-
Notifications
You must be signed in to change notification settings - Fork 553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lexical closures (my sub) have broken scoping under recursion #21987
Comments
|
Certainly odd behavior. That said, scopes generally ought to inherit variables from the parent scope unless you override that via declaration in the inner scope. If you want Given how long this has existed, I suspect patching this will have unintended consequences. This is probably a load bearing bug to some crazy script out there. Maybe better candidate for a perlcritic rule? To be fair, last I checked tail call recursion isn't encouraged in PBP. |
|
For comparison, the equivalent code using anonymous subs and lexical variables works as expected: #!/usr/bin/env perl
use strict;
use warnings;
#use feature 'lexical_subs';
sub outer {
my ($x) = @_;
my $inner = sub {
my ($label) = @_;
print "inner($label): \$x = $x at ", \$x, "\n";
};
print "outer($x): \$inner = ", $inner, "\n";
$inner->("before");
outer($x - 1) if $x > 0;
$inner->("after");
}
print "Attempt 1:\n";
outer 2;
print "\n", "Attempt 2:\n";
outer 2;
__END__Output: |
|
Does #21580 fix this? |
|
@tonycoz It does! |
Description
When lexical subs (
my sub) that close over outer lexicals are used in subs that are recursive, weird things happen. It looks like Perl doesn't realize that the inner sub is a closure and has to be allocated at runtime (once per level of recursion). Instead Perl just reuses the same inner sub, overwriting its bindings.Steps to Reproduce
Output:
Expected behavior
"Attempt 1" is the broken case. Note in particular that all three levels of
outerrecursion seem to share the sameinnersub (\&inner = CODE(0x55c73e8332b0)) and that theinner(after)calls at each level ofouterrecursion see the same$xvariable (with value 0), namely the one from the innermost (outer(0)) level of recursion."Attempt 2" is the expected behavior (I don't know why it behaves differently when called a second time). Here every level of
outerhas a differentinnersub, andinnerat each level of recursion sees a different$xvariable, both before and after the recursive call toouter.This bug is reproducible in all perl versions I've tried: 5.39.6, 5.38.2, 5.38.0, 5.36.0, 5.34.1, 5.30.3, 5.26.1, 5.20.3.
(Thanks to vms14 from libera.chat #perl for finding this!)
The text was updated successfully, but these errors were encountered: