http://www.perlmonks.org?node_id=176217


in reply to sub and anonymous sub

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

Replies are listed 'Best First'.
Re: (Revelation) Re: sub and anonymous sub
by theorbtwo (Prior) on Jun 21, 2002 at 03:25 UTC

    Why thank you; that monk using good pratice was me. The my lexicaly scopes the variable to the end of the my statement to the end of the smallest enclosing lexical block, where a lexical block is a pair of curlies, a file, or an eval string (and probably some other places, anybody?). By adding the extra {}s, you make a scope exactly as large as you need.


    We are using here a powerful strategy of synthesis: wishful thinking. -- The Wizard Book

      Thankyou kind monk theorbtwo.

      ...but look what you started me on:)

Re: (Revelation) Re: sub and anonymous sub
by BrowserUk (Patriarch) on Jun 21, 2002 at 03:50 UTC

    Thankyou! I really think I get it now. That was almost worth creating a new monk just so as I could ++ you twice!

    Just for the record - it wasn't just idle (nor idol:) curiosity, nor some form of masocism that prompted the question.

    From long experience going (way) back to school, I was never good at "rote learning". I found early on that if I could build a mental picture of the way things work, even if it was technically flawed, so long as it fit my observations, knowledge would stick. I won't embarrass myself by quoting my homebrew derivation of -b +/- b^2 -4ac/2a, but the formula stuck.

    References bookmarked for future reading when my eyes are upto it. its nearly 5 am here.

    Update:Just to show I did do my homework assignment...I especially like the "seven good uses of local()".