Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Hmmm: while(), file handle and $_ gotcha

by roboticus (Chancellor)
on Mar 06, 2009 at 12:35 UTC ( [id://748833]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, all--

I've got a question that I can't answer[1]. Given this code:

#!/usr/bin/perl -w use strict; use warnings; while (<DATA>) { if ($. % 10 == 1) { print; for my $cnt (0 .. 3) { <DATA>; # my $t=<DATA>; print; # print $t; } } } __DATA__ Line 0001 Line 0002 Line 0003 Line 0004 Line 0005 Line 0006 Line 0007 Line 0008 Line 0009 Line 0010 Line 0011 Line 0012 Line 0013 Line 0014 Line 0015 Line 0016

I expected to see this:

Line 0001 Line 0002 Line 0003 Line 0004 Line 0005 Line 0011 Line 0012 Line 0013 Line 0014 Line 0015

So imagine my surprise when I saw this:

Line 0001 Line 0001 Line 0001 Line 0001 Line 0001 Line 0011 Line 0011 Line 0011 Line 0011 Line 0011

By changing the two commented lines, I get the desired output, so my program works now. But I can't rest until I know what's causing this behavior. I expect that it has something to do with the nested while and for loops and some interaction with $_.

[1] I've tried to answer it myself, but have been unsuccessful.

  • I've looked over perlsyn (for for, while, and <>) and perlop (for the <> operator) to try to find a clue, but if it's in either of those, I missed it.
  • I also tried a Super Search, and while I found some interesting nodes, I didn't find anything that answers my question. (I can't figure out the correct search terms, so I get far too many unrelated nodes in the results list.)

Can someone whack me with a cluestick? I'd really appreciate it...

Update: Thanks to everyone who replied. I updated my script and added it to the Code Catacombs.

...roboticus

Replies are listed 'Best First'.
Re: Hmmm: while(), file handle and $_ gotcha
by moritz (Cardinal) on Mar 06, 2009 at 12:41 UTC
    Bare <DATA> outside a while doesn't assign to $_, which is why the output doesn't change in the inner loop. It's the while that does the rewriting trick to while (defined($_=<DATA>)) { ...}, as described in perlsyn.
      moritz:

      OK, that explains it. (I had an incorrect mental model: I was thinking that <FH> always put the data somewhere, using $_ unless otherwise specified. I don't know how I came to think that, as in hindsight that would be clearly stupid. Oh, well--live and learn!)

      So the correct fix to my program would is to change the inner loop from:

      for my $cnt (0 .. 3) { my $t=<DATA>; print $t; }

      to

      for my $cnt (0 .. 3) { $_=<DATA>; print; }

      so I can avoid unnecessary variables and clutter.

      Thank you!

      ...roboticus
        or
        for my $cnt (0 .. 3) { print scalar(<DATA>); }

        Hold up. How does one variable - two, if you did what I do and use a variable for the outer read as well - equate to clutter? I'd probably remove the unused $cnt if I was going to knock clutter out.

        use Modern::Perl; while (my $line = <DATA>) { if ( $. % 10 == 1 ) { print $line; } for (0 .. 3) { my $important_line = <DATA>; print $important_line; } }

        I realize this is a matter of personal aesthetics, of course. I was just a little confused how declaring and using a variable (and avoiding weird behavior from <DATA>) was better than declaring an unused variable and getting the weird behavior.

Re: Hmmm: while(), file handle and $_ gotcha
by repellent (Priest) on Mar 06, 2009 at 17:54 UTC
    Just want to point out that (nested) while (<WHATEVER>)'s clobber $_ because of no localization/lexicalization:
    while (<DATA>) { print; # $_ is "line 0001\n" open(my $FH, "<", "file") or die($!); while (<$FH>) { ... } # $_ was clobbered by: while (<$FH>) } __DATA__ line 0001

    For a better explanation, read Sins of Perl Revisited.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-19 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found