how about for(<>){...} instead of while(<>){...}

J

jidanni

Gentlemen, what peril awaits me if I use
for (<>){...} loops instead of
while(<>){...} loops?

I got the idea from perlsyn:
'Instead of using "given()", you can use a "foreach()" loop.'
And indeed I can now use when() without an enclosing given().
 
R

Randal L. Schwartz

jidanni> Gentlemen, what peril awaits me if I use
jidanni> for (<>){...} loops instead of
jidanni> while(<>){...} loops?

Try this:

@ARGV = qw(verylargefile);
while (<>) { ... }

vs

@ARGV = qw(verylargefile);
foreach (<>) { ... }

The first one has a line-at-a-time in memory, regardless of the size of
the file. The second one *must* read the *entire file* into memory
before starting the foreach loop.

Oops.

Yes, this is in Learning Perl. I recommend you read Learning Perl if
you have questions at this level.

print "Just another Perl hacker,"; # the original
 
J

jl_post

Gentlemen, what peril awaits me if I use
for  (<>){...} loops instead of
while(<>){...} loops?

I got the idea from perlsyn:
 'Instead of using "given()", you can use a "foreach()" loop.'
And indeed I can now use when() without an enclosing given().


They are very similar, but as others pointed out, for(<>) reads in
the entire input before processing the elements, whereas while(<>)
reads and processed the input line-by-line. That's because, according
to "perldoc perltrap", "while (<FH>)" is equivalent to:

while (defined($_ = <FH>))

So using for(<>) should work with small input, but be careful of large
inputs, or the entire file/input will be read in at once.

There is also another difference that is rather subtle, so it often
goes unnoticed: Because while(<>) implicitly assigns to the $_
variable, that variable WILL be different after the while-loop than
before the loop.

In contrast to the for-loop, for(<>) sets $_ to each entry of the
list that <> expands to, but the difference being that $_ will be
restored to whatever it was right before the for-loop was
encountered. (So for example, if $_ was "hello" before the for-loop,
it will be restored to "hello" when the for-loop is done.)

This is not so for while-loops. If $_ was "hello" right before the
while-loop, after the while-loop it will be set to the last line
returned from <> (accounting to any changes you make to $_ inside the
loop, of course).

The fact that for-loops restore $_ when they're finished looping
make it (usually) safe to nest them inside each each other, as even if
they all operate on $_, they'll restore the outer $_ when they're
done. I found out the hard way that while-loops don't do this, as
inner while-loops will readily "hijack" $_ without restoring them to
the value set by the outer while-loops.

So while(<>) generally uses less memory and is more efficient than
for(<>), but keep in mind that while-loops won't restore the original
value of $_ when they're done looping.

Cheers,

-- Jean-Luc
 
I

ilovelinux

   This is not so for while-loops.  If $_ was "hello" right before the
while-loop, after the while-loop it will be set to the last line
returned from <> (accounting to any changes you make to $_ inside the
loop, of course).

Not entirely correct.

while(<>) { }
is, as Jean-Luc correctly points out, equivalent to
while (defined($_=<>)) { }
and when this loop ends, $_ will be undefined.
 
J

jl_post

while(<>) { }
is, as  Jean-Luc correctly points out, equivalent to
while (defined($_=<>)) { }
and when this loop ends, $_ will be undefined.


Oh, right... while(<>) breaks out once it sets $_ to undefined
(which is one iteration after $_ is set to the last line).

Regardless, $_ won't be restored to the value it was when the
while(<>) loop was encountered (unless, of course, it was already
undefined).

Thanks for pointing that out.

-- Jean-Luc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top