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

MeowChow has asked for the wisdom of the Perl Monks concerning the following question:

Just kidding, actually I worship $_, but today, I seek wisdom for a conondrum which rattles my faith in this most holy, virtuous, and altogether nifty variable. If $_ is a global variable, how does $_ become quasi-lexically scoped:
my @l = (1,2,3,4); my @m = qw(a b c d e f g h); for (@l) { for (@m) { print " $_ " } print " : $_\n"; } outputs a b c d e f g h : 1 a b c d e f g h : 2 a b c d e f g h : 3 a b c d e f g h : 4
How does $_ get its value reset from the last 'h' value of the inner loop back to the numeric values of the outer loop? I was under the impression that $_ (namely, $::_) was a global variable. So what's story? Thanks for enlightening me...

Replies are listed 'Best First'.
Re: $_ haters anonymou
by tilly (Archbishop) on Dec 11, 2000 at 14:18 UTC
    It is indeed a global variable, but in various cases where it gets autogenerated, it is auto-localized as well.

    Warning: This means that if you begin manipulating $_ without localizing it, your caller could be unhappy.

Re: $_ haters anonymou
by repson (Chaplain) on Dec 11, 2000 at 14:21 UTC
    Have a look at this node, $_ and its localisation is discussed there.
      Oh it gets better. I don't think anyone in that node mentioned the following interesting behaviour:
      $_ = "Where did I come from?\n"; package Private; print $_;
      Isn't that odd? Try this the other way.
      package Irrelevant; $_ = "Bye, bye"; print $Irrelevant::_;
      What is going on here? Quite simple. There is a small list of "special" symbols which are always in package main by default no matter what package you are in. *_ is one. *INC is another.

      But what this really means is that you really share $_ with anything you call, making it easy to have a bad module wipe out $_ unexpectedly.

        <MODE TYPE="SILLY/STUPID">Why don't we just drop $_ and use things like $extremly_really_long_variable_name as our commonly used loop variables. This could allow programmers to write fully documented code without comments ie $variable_to_store_data_from_function_call_named_foo_and_mutate_it_with_many_operators. Think how easy it would be to write that type of code and all the time that could be saved not using punctuation like hmmm..$_, and making everything much clearer in the process. That way we could also allow all variables to be fully global because name collision should be quite difficult (hell you'll need reams of paper just to remember them, why not use a few common ones with a few character changed, such as adding _ on the end).</MODE>

        Or maybe we need an automatic local $_; at the beginning of each sub and in each package (which would solve some/all of what you were saying).
        You could put that in all your subs where you use $_ which can be called by other things.
        Then when calling other people's code enclose it in its one block:

        #.... my $var = Package::sub; #.... # changed to #.... my $var; { local $_; $var = Package::sub; } #....
        This is the only (?) way to make absolutly sure that other code won't accidently wipe $_.
        There are also other cases where we need to keep the closest eye on what is happening with $_ (for both our brains and the compiler).
        $_ = 'foo'; while (<>) for (grep {/$_/} @foo) { for (map {ord($_)} split //,$_) { while (--$h{$_}>10) {print $_} } s/a/b/g; print 'middle' . $_; } print 'outer' . $_; } print $_;
        There are 4 seperate $_'s there and while they mostly don't collide you need to keep an eye on where they are all going. This could be even worse if this kind of code is mixed in with lots of other statements.
        So $_ is just one more thing perl programmers have to keep a close eye on (but still keep on using).
        Says tilly:
        > There is a small list of "special" symbols which are
        > always in package main by default no matter what package you are in.
        > *_ is one.

        I thought that might be a useful thing to have, so I put a patch into 5.6.0 to add lots of those variables. So now if you want to have a variable that is always in package main for some reason, you can call it ${^_Ben_Tillys_Variable}, and no matter what package you are in, you always get the same thing.

        It's documented at the very end of perlvar, as is the stuff Ben was discussing.

Re: $_ haters anonymou
by extremely (Priest) on Dec 11, 2000 at 15:59 UTC
    From now on, think of for like this:
    for local $_ () { #code }

    Try this on to see that behavior: and yes, it's evil

    #!/usr/bin/perl -w use strict; sub x {print @_} $_=["ah!\n","er?\n"]; for (@$_) { x "+$_"; for (split//, $_) { x "-$_"; } }

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: $_ haters anonymou
by thealienz1 (Pilgrim) on Dec 11, 2000 at 20:15 UTC

    I bow down to this question. I have always wondered what would happen or does happen in my programs when I do this. My only questioned is : How were they, so enlightened ones, so smart to developed auto localizing?

    I am the first overweight, very tall munchkin... be very amazed.