in reply to mod_perl / Apache::Registry accidental closures
The basic solution is to wrap all top-level code that isn't inside a subroutine in a new sub, and then fixing all the problems with global variables.
In this case, something like:
use strict; use warnings; main(); # <----- change + here sub main { # <----- change + here my $foo = 5; print "Content-type: text/plain\n"; print "Content-disposition: inline; filename=foo.txt\n\n"; printf "Package: %s\n", __PACKAGE__; printf "[%s] Before: %s\n", $$, $foo; badness(5); printf "[%s] After: %s\n", $$, $foo; } # <----- change + here sub badness { my $val = shift; printf "[%s] badness: %s\n", $$, $foo; $foo += $val; }
That will not run, so we need to fix the reference to $foo in badness:
use strict; use warnings; main(); main(); main(); sub main { my $foo = 5; print "Content-type: text/plain\n"; print "Content-disposition: inline; filename=foo.txt\n\n"; printf "Package: %s\n", __PACKAGE__; printf "[%s] Before: %s\n", $$, $foo; badness(5, $foo); # <----- change + here printf "[%s] After: %s\n", $$, $foo; } sub badness { my $val = shift; our $foo; # <----- clever + trick here(*) local *foo = \shift; # <- printf "[%s] badness: %s\n", $$, $foo; $foo += $val; }
Real-life scripts will probably be harder, so make sure to run perl -c your_script.pl early and often :^)
Update: As ikegami pointed out, using my $foo = shift in badness runs, but it doesn't act the same. The (*)clever trick suggested by ikegami is a good way to circumvent that. Later iterations should probably move to a more functional approach, by making the subroutines free of side effects.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: mod_perl / Apache::Registry accidental closures
by perrin (Chancellor) on Jul 21, 2006 at 17:52 UTC | |
by imp (Priest) on Jul 21, 2006 at 18:20 UTC | |
by rhesa (Vicar) on Jul 21, 2006 at 19:13 UTC |