Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

global $_ behavior

by verdemar (Initiate)
on Dec 02, 2005 at 11:13 UTC ( [id://513560]=perlquestion: print w/replies, xml ) Need Help??

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

I *had* a problem that I solved myself, namely that the hashrefs in @list had been replaced by scalars after the second for loop in the code below. I do perl for 6 years now but I still underestimate the globalness of $_ sometimes. My question is, is my intuition so far of the line, namely that $_ feels to me more block scoped, that I don't expect the "for @list" to replace the contents of @list because they are assigned to $_? Or did I forget to read some important documentation that should be read in the beginning. I did read almost the complete Camel Book (version 2).

Here's a simplified version of the code. The work_ sub was far away in a module and difficult to find then.

Hoping for some enlightenment on the nature of $_ ...

my @list = ( { a => 1 }, { a => 15 } ); # here the values of a in the hashrefs are changed, ok! work_( $_ ) for @list; print "_=".(ref $_ ? "r.$_->{a}" : $_) . "\n" for @list; # but here the hashrefs in @list are replaced by scalars, # namely the result of the work_() call. work_( $_, 1 ) for @list; print "_=".(ref $_ ? "r.$_->{a}" : $_) . "\n" for @list; sub work_ { my ($obj, $act) = @_; $obj->{a}++; $_ = $obj->{a} if $act; }

Replies are listed 'Best First'.
Re: global $_ behavior
by dave_the_m (Monsignor) on Dec 02, 2005 at 12:14 UTC
    $_ is not block scoped; it's just an ordinary global variable that happens to be the default target for various operations. foreach just aliases the loop variable ($_ by default) to each element in turn.

    Dave.

      $_ is not block scoped; it's just an ordinary global variable that happens to be the default target for various operations.
      Thank you for this clear statement. I have been trapped by the globalness of $_ myself some times - it just feels quite natural for the beginner to assume that implicit assignment to $_ should also scope $_ implicitly to the assigning block.
      Well, it does not unless you make it explicitly local.
      I guess there are many good reasons for this :)
        There aren't really many good reasons for $_ to be global, and the main reason it's that way is simply that when Perl started out, all variables were globals. So Perl 6 is changing $_ to be implicitly lexically scoped to each sub. For those rare occasions where a sub wants to look at the $_ of its caller, it can use CALLER::<$_> to do that.
Re: global $_ behavior
by psychotic (Beadle) on Dec 02, 2005 at 11:26 UTC
    I suppose what you noticed is normal. This snippet might be enlightening.
    my $aleph = test(1,2); my $test = $_; print "$aleph : $test"; sub test { my ($a, $b) = @_; $_ = 'test'; }
    The code above produces test : test, which illustrates clearly what is going on. What works is to use local on $_ inside the subroutine. Like this:
    my $aleph = test(1,2); my $test = $_ ? $_ : '$_ is empty'; print "$aleph : $test"; sub test { local $_; my ($a, $b) = (@_); $_ = 'test'; }
    This produces test : $_ is empty. Update: I forgot to mention that this is documentend in perlvar.
      Thanks! Maybe because I only use "my", almost never "local". Especially thanks for the perlvar thing. I should have RTFM...

        It is important to understand the differences between my and local; just blindly only using my is little better than blindly only using local. Fundamentally, they're useful for different purposes, because they do different things. I like to think of my as a namespace qualifier that prevents collisions with anything outside the current block (or file). On the other hand, local has nothing whatsoever to do with namespaces but rather with time; I like to think of it as temporary assignment. It temporarily changes the value of a particular variable but allows it to revert back to its former value later.

        The upshot of this is that you can use local to change *somebody else's* variable, temporarily. For instance, you can local a package-scoped variable from a module you're using, or a global special variable like $_ or $/ or whatnot. By doing this you can change the behavior of code that uses that variable -- not just your own code, but also any code that you call (e.g., by using local on $/ you can change the way the diamond operator (which is not, strictly speaking, your code) works when you call it, but allow its behavior to revert back to "normal" later when you're done). This is tremendously useful, but it's also completely different from anything you would do with my.

        The only thing my and local have in common is that they both have to do with variable scope.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2024-04-26 08:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found