Perl Programming Page 2 - Introduction to mod_perl (part 5): More Perl Basics |
Before we proceed let's make the assumption that we want to developthe code under the The Poison Let's look at this code: nested.pl ----------- #!/usr/bin/perl use strict;
sub print_power_of_2 {
my $x = shift;
sub power_of_2 {
return $x ** 2;
}
my $result = power_of_2(); print "$x^2 = $result\n"; } print_power_of_2(5); print_power_of_2(6); Don't let the weird subroutine names fool you, the % ./nested.pl 5^2 = 25 6^2 = 25 Ouch, something is wrong. May be there is a bug in Perl and it doesn'twork correctly with the number 6? Let's try again using 5 and 7: print_power_of_2(5); print_power_of_2(7); And run it: % ./nested.pl 5^2 = 25 7^2 = 25 Wow, does it works only for 5? How about using 3 and 5: print_power_of_2(3); print_power_of_2(5); and the result is: % ./nested.pl 3^2 = 9 5^2 = 9 Now we start to understand--only the first call to the The Diagnosis Let's follow the guidelines and use the #!/usr/bin/perl -w Under Perl version 5.6.0+ we use the #!/usr/bin/perl use warnings; Now execute the code: % ./nested.pl Variable "$x" will not stay shared at ./nested.pl line 9. 5^2 = 25 6^2 = 25 We have never seen such a warning message before and we don't quiteunderstand what it means. The #!/usr/bin/perl -w use diagnostics; use strict; And execute it: % ./nested.pl Variable "$x" will not stay shared at ./nested.pl line 10 (#1) (W) An inner (nested) named subroutine is referencing a lexical variable defined in an outer subroutine. When the inner subroutine is called, it will probably see the value of the outer subroutine's variable as it was before and during the *first* call to the outer subroutine; in this case, after the first call to the outer subroutine is complete, the inner and outer subroutines will no longer share a common value for the variable. In other words, the variable will no longer be shared. Furthermore, if the outer subroutine is anonymous and references a lexical variable outside itself, then the outer and inner subroutines will never share the given variable.
This problem can usually be solved by making the inner subroutine
anonymous, using the sub {} syntax. When inner anonymous subs that
reference variables in outer subroutines are called or referenced,
they are automatically rebound to the current values of such
variables.
5^2 = 25 6^2 = 25 Well, now everything is clear. We have the inner subroutine When the inner The Remedy The An anonymous subroutine can act as a closure with respect tolexically scoped variables. Basically this means that if you define asubroutine in a particular lexical context at a particular moment,then it will run in that same context later, even if called fromoutside that context. The upshot of this is that when the subroutineruns, you get the same copies of the lexically scoped variableswhich were visible when the subroutine was defined. So you canpass arguments to a function when you define it, as well as when youinvoke it. Let's rewrite the code to use this technique: anonymous.pl -------------- #!/usr/bin/perl use strict;
sub print_power_of_2 {
my $x = shift;
my $func_ref = sub {
return $x ** 2;
};
my $result = &$func_ref(); print "$x^2 = $result\n"; } print_power_of_2(5); print_power_of_2(6); Now Let's verify: % ./anonymous.pl 5^2 = 25 6^2 = 36 So we can see that the problem is solved.
blog comments powered by Disqus |
|
|
|
|
|
|
|