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

Ahoy!

The following is a script that processes a simple text file. If you were to run it, you'd find that the WHILE loop is never exited. However, if you remove the defined keyword from the WHILE condition, it works fine. I'm told that using the defined keyword is a good scripting habit. However, it seems not to work with WHILE. Does anyone know why is it so? I'd appreciate any comments and advice, and I thank you in advance. Eldin
########################################### open QINPUT, "<", "c:/tmp.txt"; while (defined(chomp($qline = <QINPUT>))) { if (defined($qline)) { print "Q is defined!\n"; } else { print "Q is not defined!\n"; } print "\$qline: $qline\n"; } ###########################################

Replies are listed 'Best First'.
Re: WHILE and DEFINED problem
by valdez (Monsignor) on Mar 05, 2004 at 15:41 UTC
      Oopss... Seems that defined is not really needed. Thankie very muchie, Valerio! That is quite an article. I'll try to absorb it anyway. Ciao! :)

        You are welcome :) Some monks here don't agree on this; read that thread and you'll discover that the real problem lies in the wrong use of defined, see Thelonius's answer for a quick answer :)

        Ciao, Valerio

Re: WHILE and DEFINED problem
by demerphq (Chancellor) on Mar 05, 2004 at 16:03 UTC

    The idiomatic way to write that is:

    local @ARGV=qw(c:/tmp.txt); while (<>) { chomp; print "\$_: '$_'\n"; }

    And its easier to get right too. ;-)

    Update after a moments reflection: My point being that no its not better to use defined, or any of the other common pieces of advice about avoiding perl idiom. The idiom exists to make your life easy and to reduce trivial and common coding errors. If you want to have to hassle with stuff like that then do it in C.

    Update 2: Read the link valdez posted. ++ to him. Obviously its clear which camp im in, but I can see there are good points raised in that thread about using defined(). I still wouldnt though.


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi


Re: WHILE and DEFINED problem
by Thelonius (Priest) on Mar 05, 2004 at 15:45 UTC
    chomp returns "the total number of characters removed from all its arguments." In $qline is undef, chomp returns 0, which is defined.
      OIC, now it's clear. Yes, you're right, Have just verified everything out. chomp does return a value of 1 by default for every <> read-in. It actually ties with the contents $/. ICIC! Thanks again, Thelonius!
        One further note of caution. If you use while(chomp($a = <>)), then your loop will not process the last line of the file if it is incomplete (i.e. if it is missing the final newline). It is common on DOS and Windows for the last line to be incomplete.

        It is safer to put the chomp inside the body of the loop.

Re: WHILE and DEFINED problem
by kutsu (Priest) on Mar 05, 2004 at 15:58 UTC

    If you want to know if /tmp.txt has data in it use:

    $qfile = "c:/tmp.txt"; if (-s $qfile) # man perlfunc has more -s = if exist with size > 0 { open QINPUT... }

    "Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce

Re: WHILE and DEFINED problem
by dragonchild (Archbishop) on Mar 05, 2004 at 18:41 UTC
    Both valdez and demerphq have excellent (and overlapping) points. I would like to point out that the proximate issue is the use of defined() and chomp() in the while statement. chomp() never returns an undefined value. Better (though I personally write it as demerphq does) would have been:
    while (chomp(my $qline = <QINPUT>)) { # yadda, yadda, yadda }

    Though, this will fail to read the last line if it doesn't contain a newline at the end of it. (Similar to the "Incomplete last line" error vi gives you in the same situation.)

    Just do what demerphq or valdez (through the link provided) suggest.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: WHILE and DEFINED problem
by zakzebrowski (Curate) on Mar 05, 2004 at 19:15 UTC
    Aside, I've tried to re-write your code in a way I like it (which is slightly different than other ppl...
    open (IN,"<" . "c:/tmp.txt") or die "Doh: $!"; # Use ()'s, and added o +r die... sometimes that comes in hand when debugging. while(<IN>){ # $_ is set to each line for each file. my $line = $_; # Take raw form of line $line =~ chomp $line; # chomp the line. if (length($line)){ # does line have non zero length? (Sorta what y +ou're doing.) print "$line\n"; } } close IN; # Clean up.
    $.02


    ----
    Zak - the office

      Well, actually this all wrong. chomp certainly doesnt belong on the right side of a =~ operator. The way to write this is to use the idiom that dragonchild outlined:

      while (<$in>) { chomp(my $line=$_); next unless length $line; print; } __END__ # please excuse this stuff here, just doing some pmdev testing with th +is node :-) # it will be removed soon. # No indent # single space # two spaces # three spaces # four spaces # No indent # single space # two spaces # three spaces # four spaces

      :-)


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi