This is a perfectly good example of a closure -- by the book, one might almost say.
(Indeed, you want to take a good hard look at perldoc perlref. But if you're new to this, it might take a bit of study before the light comes on; so it did for me.)
Take another look at your own example code (a well-written example, thank you). You notice that when you execute &{$numbers{2}}; that $i is not really anywhere to be seen. Indeed, $i is out of scope. But by that time, you have defined three anonymous subroutines and put coderefs to them into the array @numbers. This is all fine and exactly what you want. You aren't keying %numbers with $i. You're keying with a literal, 2.
Let's move up to a more aggressive closure demo:
Here, $step and $stepper are enclosed in make_stepper(). Both are within the same lexical scope, so $stepper has no trouble at all making use of $step, which is shifted in whenever make_stepper() is called. Now $step goes out of scope as soon as its block terminates; but you might say it is "frozen" into the anonymous subroutine make_stepper() spits out.
Note that the second parm (99) is ignored when $quaddle is defined. This works as expected for 13 and 22; when $quaddle is called with no parameters, a warning is raised (and at the correct line of the code, too). This is what you want! The definition of $stepper is just that: a definition. It doesn't execute until instanced and called.
Take a look at the outputs of $i and $j. One might naively think both would be incremented.
But $j is not incremented from call to call; it goes out of scope at the end of the $stepper sub declaration and is never seen again. Each run of any of the instances creates a fresh $j, increments it to 1, prints it, and promptly forgets it.
Much more interesting is $i. This doesn't keep track of how many steppers have been made; rather it tells how often each one has been called. Note that each instance has its own counter. Think about this and see if you can tell why. Can you modify this demo to add a counter that does track how many steppers have been instanced?
Besides perldoc perlref, you might also want to take a look at Perl 5 Wiki and Perl.com on closures.
|