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

Discussion in 'Perl Misc' started by jidanni, Mar 31, 2011.

  1. jidanni

    jidanni Guest

    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().
     
    jidanni, Mar 31, 2011
    #1
    1. Advertising

  2. >>>>> "jidanni" == jidanni <> writes:

    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

    --
    Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
    <> <URL:http://www.stonehenge.com/merlyn/>
    Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
    See http://methodsandmessages.posterous.com/ for Smalltalk discussion
     
    Randal L. Schwartz, Mar 31, 2011
    #2
    1. Advertising

  3. jidanni

    Guest

    On Mar 30, 7:11 pm, jidanni <> wrote:
    > 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
     
    , Mar 31, 2011
    #3
  4. jidanni

    ilovelinux Guest

    On 31 mrt, 19:21, Jean-Luc <> wrote:
    >    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.
     
    ilovelinux, Apr 4, 2011
    #4
  5. jidanni

    Guest

    On Apr 4, 6:04 am, ilovelinux <> wrote:
    >
    > 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
     
    , Apr 4, 2011
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ^CrazyCoder^
    Replies:
    3
    Views:
    7,265
    Terrence Benade
    Sep 15, 2003
  2. David
    Replies:
    1
    Views:
    495
    David
    Jul 19, 2004
  3. Usenet Poster!!!
    Replies:
    4
    Views:
    1,827
    Eric Sosman
    Sep 30, 2004
  4. Steven

    while loop in a while loop

    Steven, Mar 24, 2005, in forum: Java
    Replies:
    5
    Views:
    2,238
    Tim Slattery
    Mar 30, 2005
  5. Replies:
    8
    Views:
    356
    Frederick Gotham
    Jun 29, 2006
Loading...

Share This Page