use strict; use warnings; sub outer { my $foo; sub inner { $foo; } inner(); } #### >perl -c test.pl Variable "$foo" will not stay shared at test.pl line 8. test.pl syntax OK #### use strict; use warnings; sub outer { my $foo; my $inner = sub { $foo; }; $inner->(); } #### >perl -c test.pl test.pl syntax OK #### use strict; use warnings; sub outer { my $inner = sub { $inner->() } } #### Global symbol "$inner" requires explicit package name at test.pl line 6. test.pl had compilation errors. #### use strict; use warnings; sub outer { my $inner; $inner = sub { $inner->() } } #### >perl -c test.pl test.pl syntax OK #### # ReleaseTracker.pm # This "module" simply provides "o()", a # func that creates a simple object whose # sole purpose is to print "Destroyed" when # it is freed. The inner workings are not # relevant to this example. use strict; use warnings; package ReleaseTracker; BEGIN { our @EXPORT_OK = qw( o ); require Exporter; *import = \&Exporter::import; } sub new { return bless(\(my $o), $_[0]); } sub DESTROY { print("Destroyed\n"); } sub o { ReleaseTracker->new(); } 1; #### use strict; use warnings; use ReleaseTracker qw( o ); sub outer { # Variables that are read by each recursive instance. my $var = shift @_; my $helper; $helper = sub { no warnings 'void'; "do something with $var and @_"; $helper->(@_); }; #$helper->(@_); } outer( o() ); END { print("On program exit:\n"); } #### >perl test.pl On program exit: Destroyed <--- BAD! #### use strict; use warnings; use ReleaseTracker qw( o ); sub outer { # Variables that are read by each recursive instance. my $var = shift @_; local *helper = sub { no warnings 'void'; "do something with $var and @_"; helper(@_); }; #helper(@_); } outer( o() ); END { print("On program exit:\n"); } #### >perl test.pl Destroyed On program exit: <-- good #### sub outer { ... local *helper = sub { ... helper(...); ... }; helper(@_); } #### sub outer { ... Y( sub { my $helper = shift @_; sub { ... $helper->(...); ... } } )->(@_); } #### sub outer { ... my $helper; $helper = sub { ... $helper->(...); ... }; weaken($helper); $helper->(@_); }