|Perl: the Markov chain saw|
(Revelation) Re: sub and anonymous subby Revelation (Deacon)
|on Jun 21, 2002 at 03:05 UTC||Need Help??|
Here's a little explanation, using as little perlguts as possible :)
First of all What is lexical scoping? We put a variable into play, until it leaves the range we decided for it to be able to live within. Lexical scoping creates private constructs that are only visible within their scopes, can't be touched anywhere else. That scope is interpreted into the program, and should be obvious from the code. Think of 'lexical scoping (my)' as a person, who can only live within a certain range of time, and can't be everywhere at once; we declare this person out of scope later on, and he can no longer be modified or called back in name, although we may see the effects of his actions lingering. Outside of their scope, variables (and people) are invisible and can't be altered in any way. That's why you can talk behind a lexical variable's back :)
Note: Local() creates temporary variables, and is not lexical, but dynamic. This means that the value is global, but is temporarily local()ized. Localized variables are temporary objects, whose values reset when go out of their scope. Localization has been optimized to not create temporary objects in some cases, but that's talk for another node.
Why do we scope lexically: Because we've been told to do so :) Seriously though, there's no necesity to scope lexically, unless you're coding mod_perl scripts, in which case you may end up with memory leaks and the like. However, it is good programming practice as it frees up memory when the subroutine is not being executed. Lexical scoping can save us from name space problems, as well. You might not want to alter variables in subroutines that have the same name as global variables.
How does lexical scoping Work : my($x) creates a new variable that is only visible in the current subroutine. This is done at compile-time, so is called lexical or static scoping. By putting brackets (1 And 4) around the code, we identify it as an 'enclosed block*' From here, perl takes over, seeing the my you have given it, perl scopes the variable lexically, and tells us to get rid of it, when we're done; however, everything within that block, can still see our lexical value, and will be able to use it. When we close the block, the variable goes can be declared and used again!
How did this apply to your code: So for all intents and purposes, you are perfectly right. Your code creates an enclosed entry, with an initialized variable after 1, that disappears at 4. It doesn't exist when recursive() is invoked (5); however, we have told the recurse subroutine to access data *within* the lexical scope, so it is possible to access that data. Frankly, his idea to lexically scope into an enclosed block was crafty manipulation of the code, that merits a thumbs up. Your friendly monk enforced good coding practices on the fly, and saving us the pains that I have previously outlined. The code is a good example of a monk using good practice, although it's not necessary for functional code (try to remove the parens.) :)
A good read would be This meta tutorial, when you get the time. It explains the issue in perlgutsy language, but also clears up most questions one could have. Dominus has a good reference as well, located here. Localizing variables is a tad bit more complicated than I made it out to be, but these two tutorials can iron you out on the specifics, and interesting little facts about them.
I hope I've given you enough of a primer to understand what lexical scope is, and how and when to use my.
*A `my' declares the listed variables to be confined (lexically) to the enclosing block, conditional (if/unless/elsif/else), loop (for/foreach/while/until/continue), subroutine, eval, or do/require/use'd file