--- "Randal L. Schwartz" <[EMAIL PROTECTED]> wrote:
> >>>>> "Paul" == Paul <[EMAIL PROTECTED]> writes:
>
> Paul> This is lovely, and a great opportunity to show some new toys
> Paul> to beginners, as well as some well-placed caveats. With your
> Paul> indulgence, I'll try to break this down for the newbies. :)
>
> Great!
>
> Paul> Be careful with this, though -- if you call some other function
> Paul> from this scope, the value of $SIG{__WARN__} will still be the
> Paul> routine that increments $bad, but it won't be able to see the
> Paul> $bad we made with my()!
>
> Wrong. It'll still work! It's a closure!
>
> (now explain that... :)
LOL!!!! Better and better!
I'm embarrased not to have thought of that, but that's why I love this
list. It keeps us all on our toes.
Though it still might not do what you expect in the other
function...especially if that function were counting on a __WARN__ hook
that had been globally setr before the call. Yes?
For the audience:
Perl's idiom for making private static variables is to put both the
global function definition and a my() variable in the same scope, but
don't put the var inside the function, like this:
{ # start a scope
my $static; # exists only in this scope
sub func { # global function
print ++$static; # increments
} # and of func
} # end of external scope
Now, $static doesn't exist beyond the boudaries of that external scope,
but the global function references it, *so the variable doesn't die*
while the function exists. Someone remembers it, and it just so happens
that the someone is this global function. (If you read docs that talk
about "deep-binding", think of this.)
So, back to Randall's code.
My declared a variable $bad using my, then assigned a closure (an
anonymous function) to the __WARN__ hook of the %SIG signal handler
table. %SIG is global, even though the value was swapped with local().
If you call out of the current function while the local() is still in
effect, the *global* value of $SIG{__WARN__} is still the anonymous
function. That closure was compiled in tha same scope as the my()
variable and accesses that variable, so the closure containes a
reference to the private variable $bad. That means it knows where to
look, even when not in that scope. Thus, this handler will still work,
even though you probably wouldn't want it to!
Moral: if you must use local() to accomplish something, be aware of
what it does, and that it can affect things outside that scope if you
are careless. Use my() when you can, BUT know that you can't on certain
magical variables (c.f. perldoc perlvar for some good examples. =o)
BTW, this is another use of the same sort of trick as
{ local $/ = undef;
$file = <FH>; # slurp the whole file into $file
}
which is more efficient than
while(<FH>) { $file .= $_ }
or
$file = join '', <FH>;
Still, I have a coworker who swears by the latter as more work, yes,
but MUCH more readable in his opinion.....
And now that I've digressed so... =o)
Aside from the divergence to an only marginally related topic, how'd I
do? List? Randall?
Finally, one last caveat: if you didn't understand the explanation,
it's either because I did it poorly, or because these are things beyond
your experience. Read the label: CAUTION! HANDLE WITH CARE.
Paul ;o]
__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail - only $35
a year! http://personal.mail.yahoo.com/