Re: static variable hack
by ikegami (Patriarch) on Oct 29, 2007 at 19:37 UTC
|
When my is encountered at run-time, a directive is placed on the stack to clear the variable. Since you're not executing my, the directive is not placed on the stack, so the variable doesn't get cleared.
The docs warn against using this side-effect of internal mechanics. (Emphasis in original.)
Note: The behaviour of a my statement modified with a statement modifier conditional or loop construct (e.g. my $x if ...) is undefined.
If you wish to have a static variable, use the following. (Surrounding curlies are optional.)
{
my $static;
sub func {
...
}
}
See recent thread Lexical scope variable is not undef'ed. | [reply] [d/l] [select] |
|
{
my $static;
sub func {
...
}
}
I'd updated that to:
BEGIN {
my $static= ...;
sub func {
...
}
}
The BEGIN allows this to work just fine under mod_perl, and protects against people calling the subroutine before the $static is initialized. The subroutine is defined when it is compiled, so it is best to initialize the $static before that.
| [reply] [d/l] [select] |
|
Right, thanks. Also I have ran this code with "use strict;". If, "my" isn't executed, why doesn't the "strict" complain ?
| [reply] |
|
Creating the variable is my's compile-time effect. The my gets compiled whether it gets executed or not.
| [reply] [d/l] [select] |
|
|
Re: static variable hack
by FunkyMonk (Chancellor) on Oct 29, 2007 at 19:36 UTC
|
You won't find an explanation of it it the documentation, because the behaviour is undefined. perlsyn is the best you'll get:
NOTE: The behaviour of a my statement modified with a statement modifier conditional or loop construct (e.g. my $x if ... ) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.
| [reply] [d/l] [select] |
Re: static variable hack
by shmem (Chancellor) on Oct 29, 2007 at 20:19 UTC
|
This line
my $static = 42 if 0;
is optimized away after compilation, because the 0 is a constant:
qwurx [shmem] ~ > perl -MO=Deparse
sub foo {
my $static = 42 if 0;
print "static is now $static\n";
$static++;
}
foo() for 1..5;
__END__
sub foo {
'???';
print "static is now $static\n";
$static++;
}
;
foo foreach (1 .. 5);
__DATA__
- syntax OK
Note the '???' showing a statement swallowed by the optimizer.
Because optimization happens after compile, the lexical variable declared via my already
has been seen and allocated for the subroutine's scope.
That's why that construct passes strictures. And - that' the hack - because the my declaration isn't
seen ever again at runtime, the lexical inside that sub doesn't get cleared on subsequent invocations of the sub.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
|
Overall right. Just nitpicking two details.
First, optimization is not a factor. It's simply whether the my gets executed or not.
Second, you're also off on the timing. Clearing occurs at end of scope. It's triggered by the my, but it doesn't occurs when the my is encountered. (By the way, that's also when a new my variable is created if the refcount is greater than 1.)
Both points can be observed in
sub foo {
my ($reset) = @_;
my $x if $reset; # Will reset at end of scope if $reset is true.
return ++$x;
}
print foo(0), "\n"; # 1
print foo(0), "\n"; # 2
print foo(1), "\n"; # 3
print foo(0), "\n"; # 1
print foo(0), "\n"; # 2
| [reply] [d/l] [select] |
Re: static variable hack
by KurtSchwind (Chaplain) on Oct 29, 2007 at 20:02 UTC
|
| [reply] |
|
sub foo { my $var if 0; $var++; print "var is now $var\n"; }
and
sub foo { my $var ; $var++; print "var is now $var\n"; }
| [reply] [d/l] [select] |