Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Re: Playing with non-localized $_ in nested loops.

by gaal (Parson)
on Aug 22, 2004 at 22:21 UTC ( #384985=note: print w/replies, xml ) Need Help??

in reply to Playing with non-localized $_ in nested loops.

Regarding what surprised you, a comparison of the output of these two one-liners affirms your conjecture. Neither of the following warns directly about a read:

% perl -le 'warn "a"' a at -e line 1. % echo "" | perl -le '<>; warn "a"' a at -e line 1, <> line 1.
Once a <> has been invoked, warnings will include latest readline coordinates regarless of what triggers them.

By the way, this issue has bitten real live sites. I gave a lightning talk in YAPC::Israel::2004 about this.

Replies are listed 'Best First'.
Re^2: Playing with non-localized $_ in nested loops.
by BrowserUk (Patriarch) on Aug 22, 2004 at 22:29 UTC

    You'll only get the extra info if the filehandle read from is still open. closing the file (ARGV in the case of the diamond operator) switches it off again.

    P:\test>echo "" | perl -wle "<>; warn 'Erk!'" Erk! at -e line 1, <> line 1. P:\test>echo "" | perl -wle "<>; close ARGV; warn 'Erk!'" Erk! at -e line 1.

    Explicitly closing DATA once the loop completes is useful sometimes.

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re^2: Playing with non-localized $_ in nested loops.
by davido (Cardinal) on Aug 23, 2004 at 02:13 UTC

    I read the slides from your lightning talk. They were interesting. One thing that I might add (or otherwise comment on) is the suggestion that while() doesn't localize $_. While this is true, it's probably more accurate to state that <FH>; doesn't localize $_. Because the fact is that while() isn't itself acting on $_. The action is carried out by the diamond operator implicitly spilling its guts into $_. while() doesn't really have much to do with it, though we get in the habbit of thinking that it does since the while( <> ) construct is so common, and since foreach loops default to acting upon $_.

    Also commenting on your slides (not having heard the lecture), foreach is the exception as you said, but this is because foreach works in an entirely different way than while(). With respect to foreach, it is the loop construct itself that acts upon $_, in a very special way. We even write it in a very special way (if we write it out longhand):

    foreach $_ ( list )

    ...that's how foreach deparses with B::Deparse. Your slides mention that foreach is the exception. While it is an exception, it is not the only one. map also is a looping mechanism where $_ is localized. Consider the following code:

    $_ = "Test string\n"; my @array = map { $_ = chr $_ } 32 .. 64; print $_; __OUTPUT__ Test string

    As you can see, the use of $_ inside of map works a lot like the iterator of a foreach loop, in that it serves as an alias to the elements of the input list (ok, my example doesn't demonstrate this, but it's true), and in that it is localized (my snippet shows this to be the case).

    Just a few observations and additional meditations... ;)


      The automatic setting of $_ comes from the combination of while() and readline. Just a plain readline won't do it. Nor does while with just any operator do the implicit assignment.
        <DATA>; print $_; __DATA__ This is a test. __OUTPUT__ Use of uninitialized value in print at line 8, <DATA> line 1 +.

        Hmm... You're right. There goes that theory. ;) I was erroneously sure that the while() loop's conditional had nothing to do with the fact that the diamond operator feeds $_. Thanks for the enlightenment. :D


      for, map, and grep: these three constructs localize $_. But in fact, map and grep are more vulnerable than foreach, because they don't give you the choice of using a lexical as your aliased iterator (iterant?). I did mention this in the talk though I guess the emphasis is stronger when you have more than the slides :)

        There is a difference between localizing $_ and aliasing it to something else. Do not confuse the two.

        Note also that there is no construct which implicitly localizes $_, but there are several which alias it to something else.

        Obviously, while(<FH>) cannot alias the variable to anything, because one would have to be able to expect that modifying $_ would actually modify the file. Instead, readline returns a copy of the data found in the file.

        It really is obvious and very consistent if you think about it. Perl just DWIMs well enough in so many cases that it's easy to overlook some of the ramifications of any single operation.

        Makeshifts last the longest.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://384985]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2023-12-02 04:35 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (13 votes). Check out past polls.