in reply to Re^2: OUR declaration
in thread OUR declaration
Perl does not support nested named subroutines. If you need nested subroutines you can use anonymous subroutines but this makes stackdumps nigh-on unreadable. Using file-scoped lexicals with local() would be a solution but as I said before you can't do that. So the next best thing is our().
I once wrote some twisted recursive code to render tables of tables in HTML. Sometimes it would cluck() and I'd get a backtrace with a dozen levels of anonynous subroutine.
use AtExit; sub awful { my ($various,%shared,@vars); my ($recusive1,$recursive2); my $cleanup = AtExit->new(sub{ undef $recursive1; undef $recursive2; }); $recursive1 = sub { # Do stuff with $various,%shared,@vars and make further calls +to # $recursive1->() and $recursive2->() } $recursive2 = sub { # Do stuff with $various,%shared,@vars and make further calls +to # $recursive1->() and &$recursive2->() and call frobnicate($recursive1); } $recursive1->(); }
I decided it was more maintainable as:
our ($various,%shared,@vars); sub awful { local ($various,%shared,@vars); recursive1(); } sub recursive1 { # Do stuff with $various,%shared,@vars and make further calls to # recursive1() and recursive2() } sub recursive2 { # Do stuff with $various,%shared,@vars and make further calls to # recursive1() and recursive2() frobnicate(\&recursive1); }
Note that frobnicate may call awful() but this inner awful() would not want to share the outer awful()'s variables.
Now there is a potential problem here if frobnicate() store its CODE reference argument somewhere and thus manages to call back to recursive1() after awful() completes or for that matter during a reentrant call of awful(). But I happened to know that wasn't going to happen.
There's a similar problem to the nested subroutine problem with regex containing (?{}) except you don't get the warning.
use strict; use warnings; sub foo { my $x = shift; print "$x "; sub foo1 { print "$x "; # Warning } foo1(); '' =~ /(?{ print "$x\n" })/; # No warning } foo('Hello'); # Prints 'Hello Hello Hello' foo('Goodbye'); # Prints 'Goodbye Hello Hello' sub bar { local our $x = shift; print "$x "; sub bar1 { print "$x "; } bar1(); '' =~ /(?{ print "$x\n" })/; } bar('Hello'); # Prints 'Hello Hello Hello' bar('Goodbye'); # Prints 'Goodbye Goodbye Goodbye' __END__