Now you understand that there are cases where your normal subroutines can
become inner, since if your script was a simple:
simple.pl --------- #!/usr/bin/perl sub hello { print "Hello" } hello();
Wrapped into a run()
subroutine it becomes:
simple.pl --------- package cache::simple_2epl; sub run{ #!/usr/bin/perl sub hello { print "Hello" } hello(); }Therefore,
hello()
is an inner subroutine and if you have used
my()
scoped variables defined and altered outside and used
insidehello(),
it won't work as you expect starting from the
second call, as was explained in the previous section.Remedies for Inner Subroutines
First of all, there is nothing to worry about, as long as you don't forget
to turn the warnings On. If you do happen to have the "my()
Scoped Variable in Nested Subroutines" problem, Perl will always alert you.Given that you have a script that has this problem, what are the ways to
solve it? There are many of them and we will discuss some of them here.We will use the following code to show the different solutions.
multirun.pl ----------- #!/usr/bin/perl -w use strict; for (1..3){ print "run: [time sh]n"; run(); } sub run{ my = 0; increment_counter(); increment_counter(); sub increment_counter{ ++; print "Counter is equal to !n"; } } # end of sub runThis code executes the
run()
subroutine three times, which in
turn initializes thevariable to 0, every time it is executed and then calls the inner
subroutineincrement_counter()
twice. Sub
increment_counter()
prints's value after incrementing it. One might expect to see the following
output:run: [time 1] Counter is equal to 1 ! Counter is equal to 2 ! run: [time 2] Counter is equal to 1 ! Counter is equal to 2 ! run: [time 3] Counter is equal to 1 ! Counter is equal to 2 !But as we have already learned from the previous sections, this is not what
we are going to see. Indeed, when we run the script we see:% ./multirun.plVariable "" will not stay shared at ./nested.pl line 18. run: [time 1] Counter is equal to 1 ! Counter is equal to 2 ! run: [time 2] Counter is equal to 3 ! Counter is equal to 4 ! run: [time 3] Counter is equal to 5 ! Counter is equal to 6 !Obviously, the
variable is not reinitialized on each execution of
run().
It
retains its value from the previous execution, and sub
increment_counter()
increments that.One of the workarounds is to use globally declared variables, with the
vars
pragma.multirun1.pl ----------- #!/usr/bin/perl -w use strict; use vars qw(); for (1..3){ print "run: [time sh]n"; run(); } sub run { = 0; increment_counter(); increment_counter(); sub increment_counter{ ++; print "Counter is equal to !n"; } } # end of sub runIf you run this and the other solutions offered below, the expected output
will be generated:% ./multirun1.pl run: [time 1] Counter is equal to 1 ! Counter is equal to 2 ! run: [time 2] Counter is equal to 1 ! Counter is equal to 2 ! run: [time 3] Counter is equal to 1 ! Counter is equal to 2 !