Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Whether to use local()

by jerrygarciuh (Curate)
on Mar 15, 2002 at 18:28 UTC ( #152040=perlquestion: print w/ replies, xml ) Need Help??
jerrygarciuh has asked for the wisdom of the Perl Monks concerning the following question:

While this is not an OO question, it was prompted by theDamian's OO Perl (which I got for my b-day (not bidet). OO Perl Ch1 talks about Objects sharing attributes and methods they need and not those they don't. I have also seen objections here at PM that a var declared with my at the top level of a script is a pseudo-global and therefore bad form.

My question is whether you should be concerned with scope if $new_mail needs to be shared between sub update_mail_list and sub read_mail_list etc. Do you take care to use local to control scope? Or do you simply declare my $new_mail at the topmost level so the whole script has access? The latter is so easy, why would you go to the trouble of using local if you aren't trying to keep some private value of $new_mail somewhere?

I hope my question is clear.
TIA
jg
_____________________________________________________
It's not my tree.

Comment on Whether to use local()
Select or Download Code
Re: Whether to use local()
by shotgunefx (Parson) on Mar 15, 2002 at 18:31 UTC
    local only works on global variables. (Anything in the symbol table.) my (lexicals) variables don't exist in the symbol table.

    update
    I realized I didn't really answer the question you where trying to ask. Declaring a my variable at the top of a file at worst is polluting one file. If you are writing the code and the files aren't huge, it's not all that hard to avoid shooting yourself in the foot with a little dilligence.

    -Lee

    "To be civilized is to deny one's nature."
      So you can't use local on vars you create if you are going to use strict? That seems strange to me.
      TIA
      jg
      _____________________________________________________
      It's not my tree.
        You can use both globals (package vars) and lexicals under use strict though globals need to be fully qualified ( $My::Mail::Server= "255.255.255.255";)
        Though globals are usually (not always) the wrong way to go. The idea of lexicals are that they only exist in a scope thereby limiting access. What local does is let you temporarily save a value for a package var. It's a runtime trick and my is (mostly) a compile time trick.

        The lowdown is package vars exist in packages and any can be accessed from any package. my vars exist in the scope they where declared in and cannot be accessed outside so you don't have to worry about other subs/modules etc clobbering your values. You usually use local to save the value of $/ or $_ so you don't screw up code that calls your code. It has some other uses but that's one of the main one. There are probably a lot better explainations than mine and I'm sure if you do a search for lexical / package / global you will find a wealth of info here in the monestary.

        UPDATE
        here is a great FAQ on "Coping with Scoping" by dominus. It's a far better explaination than mine.

        -Lee

        "To be civilized is to deny one's nature."
      local only works on global variables

      my %foo; $foo{bar} = " odd then?\n"; { local $foo{bar} ="Isn't this"; print $foo{bar}; } print $foo{bar};
      :-P
        I know about local on hash elements and array elements but thought it would complicate the explanation for him. Just like I omitted PadWalker from the explanation of accessing lexicals. Point taken though. Was local on hash/array elements added as a hack for signal handlers? It seems the only real use that I've seen. Or is it used internally when you localize a package var in the symbol table seeing a package is in a sense a hash?

        -Lee

        "To be civilized is to deny one's nature."
(jeffa) Re: Whether to use local()
by jeffa (Chancellor) on Mar 15, 2002 at 18:45 UTC
    "...why would you go to the trouble of using local if you aren't trying to keep some private value ... somewhere?"

    Personally, i wouldn't. But the caveat depends on what kind of program you are writing.

    When i write utility scripts, avoiding global variables is usually a waste of typing to me - i use them. Keep in mind that i do have a CS degree and my professors would never allow us to use globals ever anywhere! I appreciated that, but now that i understand the rules, i can break them. >:)

    Let's say that i am writing a larger program. Then i would strongly consider OO. OO is good for eliminating globals, because you instead have accessor methods (considering, of course, that it is good OO).

    Finally, local vs. my - in my limited experience with local, i only use it to erase Perl's built-in variables, like $/ for slurp mode (thanks again tye!):

    my $slurp = do {local $/; <FH>};
    All of my variables are declared with my. To be honest, i am still missing the picture of when you need our.

    Hope this helps :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      Does this snippet explain our for you jeffa ?

      # comment use strict in and out # use strict; package Foo; our $global = 'global '; $not_so_global = 'not so global'; package Bar; print "Full package name: ", $Foo::global, $Foo::not_so_global, "\n"; print "No package name: ", $global, $not_so_global, "\n";

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        Ahhhh, i am starting to see now:
        • my declares a local variable which is not found in a package's symbol table
        • a local var does show up in the symbol table, but if you use strict, then you have to fully qualify the variable name (that is, prefix the package name)
        • our handles the strict vs. non-fully qualified local vars
        perrin pointed me to CPAN and the Devel::Symdump module. Here is another snippet to help explain:
        #!/usr/bin/perl #use strict; use Devel::Symdump; my $obj = Devel::Symdump->new('Foo'); print map {"$_\n"} $obj->scalars; package Foo; local $Foo::qualified; local $unqualified; our $our; my $my;
        Which (without use strict) produces this ouput :
        Foo::qualified
        Foo::our
        Foo::unqualified 
        
        If strict is turned on, then $unqualified will cause a compliation error. I think i get it now! :)

        Thank you tachyon, perrin, and also rob_au for pointing out What is it adding to my symbol table?.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Whether to use local()
by tachyon (Chancellor) on Mar 15, 2002 at 18:50 UTC
Re: Whether to use local()
by erikharrison (Deacon) on Mar 15, 2002 at 18:50 UTC

    local() gives a local value to a global variable. A local variable is visible to called subs but not calling subs. It seems to me that it would be difficult to use local to have class data. I think that this is one of those cases where a global is the correct solution to a problem. One shouldn't use globals to pass data to a subroutine - it's bad form, and it's confusing. However, since a class is a package in Perl, then a class global is the best way to store class data. Declaring the global with my makes it impossible for anyone else to accidentally change the variable outside of the lexical scope. I would also probably use a hash to make it very clear where the data is coming from:

    package Class::Foo; my %ClassData = (); #methods here

    Note however, that you have to be very careful if you are putting the class in the same file as the code which uses it - as a file (and NOT a package) delimits lexical scope, your class data might leak into the main program even if declared with my.

    Cheers,
    Erik
Re: Whether to use local()
by dws (Chancellor) on Mar 15, 2002 at 18:53 UTC
    My question is whether you should be concerned with scope if $new_mail needs to be shared between sub update_mail_list and sub read_mail_list etc.

    I would be concerned, but I'd balance that concern against the size and complexity of the module, and whether there's a likelihood that the module would be extended or subclassed.

    In your example, a global variable with package scope that is shared between two methods throws a major wrench into attempts to subclass either of the methods. Whether to use local depends on how the variable is shared.

Re: Whether to use local()
by derby (Abbot) on Mar 15, 2002 at 19:14 UTC
    jg,

    OoooOOhh ... not only the messy mindfield of globals -vs- proper scope but also the messy mindfield of where to define subroutines (at the top before an implicit main, or at the bottom after the implicit main). You should get lots of comments to this.

    You should definetly minimize globals by using the my operator. Check out "Private variables via my()" section in perlsub. The thing to remember about using my is that A "my" declares the listed variables to be local (lexically) to the enclosing block, file, or "eval". So if you use my at the top of a package, all the methods/functions/subroutines defined after can have access to that lexical.

    Now the big question is "is that a big deal?" I disagree with a lot of my fellow monks and feel it is not. demerphq has named this unintended globals but that would be only if you accessed the lexical in your methods. My fellow monks contend (and rightly so) that if you define your functions first and then your lexicals, perl will complain. I feel that's too big a price to pay over readability (but I've agreed to disagree about this point). My own opinion is to better know the code you're writing/maintaining and ensure you don't utilize file scoped lexicals (can anyone say code review).

    Now when talking about packages, especially those which will be OO classes, the norm is to usually hang all the objects attributes off a blessed hash - your need for a package wide lexical is pretty small. Your need for true global variables is small also and should be kept to only those constructs which help with loading and inheritance (@ISA, @EXPORT, @EXPORT_OK).

    -derby

      You should avoid using "unintended globals" or "file scoped lexicals" (whatever you want to call them) when you are using mod_perl. The mechanism mod_perl uses to keep code in memory will turn your subs into closuresand the values of lexically scoped variables will be stored and used with every execution. For an excellent write up see The mod_perl Guide section my() Scoped Variable and Nested Subroutines.


      TGI says moo

Re: Whether to use local()
by dragonchild (Archbishop) on Mar 15, 2002 at 19:22 UTC
    If $new_mail needs to be shared between two object methods, it makes sense to me to make $new_mail an attribute of the class you're in. (It's irrelevant if it's class data or instance data.)

    Now, the question probably becomes "How do I make class data"? The best answer to that that I've found is to simply make a file-scoped lexical. You do have inheritance questions if you want children access to class data of their parents, but that's an implementation question. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Whether to use local()
by YuckFoo (Abbot) on Mar 15, 2002 at 19:27 UTC
    The recommendation from perlman:perltoot always seemed reasonable to me:

    
           But more often than not, you just want to make your class
           data a file-scoped lexical.  To do so, simply put this at
           the top of the file:
    
               my $Census = 0;
    
           Even though the scope of a my() normally expires when the
           block in which it was declared is done (in this case the
           whole file being required or used), Perl's deep binding of
           lexical variables guarantees that the variable will not be
           deallocated, remaining accessible to functions declared
           within that scope.  This doesn't work with global
           variables given temporary values via local(), though.
    
    
    YuckFoo
Re: Whether to use local()
by PrakashK (Pilgrim) on Mar 15, 2002 at 19:38 UTC
    My question is whether you should be concerned with scope if $new_mail needs to be shared between sub update_mail_list and sub read_mail_list etc.
    One trick I sometimes use to share a variable among multiple subroutines, without making it a package variable is to enclose all of them in a block.
    { my $new_mail; sub update_mail_list { # uses $new_mail } sub read_mail_list { # uses $new_mail } }
    What do monks think about this style?

    Thanks,
    /prakash

      I was wondering if someone was going to bring this up. To me, this is the best way to share a variable between two (or more) subroutines.

      Just bear in mind, though, that you may receive puzzling errors regarding $new_mail being undefined, depending on where this code appears in the file, and how and when control gets passed to update_mail_list() or read_mail_list().

      Best practices would suggest that rathing than enclosing the variable and the referring subs in bare { } braces, you should use a BEGIN { } block. This will ensure that $new_mail gets set up on the lexical pad before you get around to using it.


      print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
      I use this as well.

      But don't if you are going anywhere near mod_perl. Else much grief awaits you...

        That should only be a problem if you do that in an Apache::Registry script (and any similar beasts, if they exist). If its in a module use'd by an A::R script (and maybe even in a non A::R handler?), it should be ok (if I'm not mistaken, and if you're careful).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://152040]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2014-07-13 01:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (244 votes), past polls