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

I'm learning Perl through a book I'm reading and I'm doing the exercises in the chapters. This one asks me to write a program to accept input until a "." appears in a line by itself...then print, in reverse order, the input back. Here's my code:
#!Perl -w use strict; use diagnostics; my (@lines); while (<> and $_ ne ".\n") { push @lines,$_; } foreach (reverse @lines) { print; }
I'm getting an error message and I don't know what it means. It says something about an uninitialized string in ne. <W uninitialized> An undefined value was used as if it were already declared.... What am I doing wrong?
There are some things we will never know... And we will never know that we don't know them...

20050511 Edit by castaway: Changed title from 'Newbie Question'

Replies are listed 'Best First'.
Re: Uninitialized string warning
by Sandy (Curate) on May 11, 2005 at 19:53 UTC
    Hi Richard,

    I am not certain of the exact reasons, but I did have the same problem myself once, and it boils down to:

    The automatic initialization of $_ happens only if the while loop looks like while (<>)

    Anything else fouls it up. e.g.
    This works

    # ctrl -c to exit (this is only example code!!!) while (<>) { print "\$_ = <$_>\n"; }
    e.g.
    This does not work
    # ctrl -c to exit (this is only example code!!!) while (<> and 1) { print "\$_ = <$_>\n"; }
Re: Uninitialized string warning
by ikegami (Patriarch) on May 11, 2005 at 19:56 UTC

    What the others failed explain is that <> only assigns it's value to $_ when it is the entirety of the while's condition. When you added the and bit, it ceased to be special. In other words,

    while (<>) {
    is equivalent to
    while (defined($_ = <>)) {

    but
    while (<> and ...) {
    is equivalent to
    while (<> and ...) {

    Notice the lack of $_ = in the second case.

    That's why
    while (defined($_ = <>) and $_ ne ".\n") {
    is needed.

    Update: It seems that Sandy explained the same thing while I was writting my reply.

      Update: It seems that Sandy explained the same thing while I was writting my reply.

      I am curious. What is the purpose of this update?

        It's a retraction of my "What the others failed explain" qualifier.
Re: Uninitialized string warning
by xorl (Deacon) on May 11, 2005 at 19:41 UTC
    You don't want the and $_ ne ".\n" in the condition statment. Take that out and put something like: if ($_ eq ".\n") {last;} just before the push line.
    #!/usr/bin/perl -w use strict; use diagnostics; my (@lines); while (<>) { if ($_ eq ".\n") { last;} push @lines,$_; } foreach (reverse @lines) { print; }
Re: Uninitialized string warning
by Adrade (Pilgrim) on May 11, 2005 at 21:22 UTC
    another one just for fun
    unshift(@w,$q) while(($q = <>) && ($q ne ".\n")); print @w
    Best,
      -Adam
Re: Uninitialized string warning
by phaylon (Curate) on May 11, 2005 at 21:05 UTC
    Just for fun:
    use warnings; use strict; my @lines; push @lines, $_ while do { $_ = <> } ne ".\n"; print reverse @lines;

    Ordinary morality is for ordinary people. -- Aleister Crowley
Re: Uninitialized string warning
by Transient (Hermit) on May 11, 2005 at 19:45 UTC
    Or you could change it to:
    use strict; my (@lines); while (defined($_ = <>) and $_ ne ".\n") { push @lines,$_; } foreach (reverse @lines) { print; }