Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re^4: $_ not set in while <>

by Marshall (Canon)
on Jun 06, 2021 at 05:02 UTC ( #11133576=note: print w/replies, xml ) Need Help??


in reply to Re^3: $_ not set in while <>
in thread $_ not set in while <>

The condition is not "dense".
The condition is whether or not the input line is "quit" or some form of that.
All that matters is the part after the last comma.

Works fine for me:

use strict; use warnings; my $line; while ( (print "list of letters: "),$line=<>, $line !~ /\s*quit|exit|q +\s*$/i) { print "doing something with $line\n"} __END__ Example run: C:\Users\xxx\Documents\PerlProjects\Monks>perl commandloopX.pl list of letters: 234 doing something with 234 list of letters: asdf doing something with asdf list of letters: quit C:\Users\xxx\Documents\PerlProjects\Monks>
Update: I guess this could be, using "and" instead of comma.
print() does return a true value, but nobody checks it.
while ( (print "list of letters: ") and defined ($line=<>) and $line ! +~ /\s*quit|exit|q +\s*$/i)
The comma operator is completely fine in Perl. This is more common in C code.

Update: Oh, the parens around the print are required in order to get the prompt onto the screen.
I never use a while(1) statement except perhaps in a server process.

Another Update:
I did run your code. I did require the addition of a "my declaration" for $line.
Your code does work albeit as wordy and hard to understand as it is.
I am sure that there are many Monks who will disagree with style issues!

use strict; use warnings; my $line; while (1) { print "list of letters: "; defined( $line = <> ) or last; $line !~ /\s*quit|exit|q\s*$/i or last; # Do something with $line. } __END__ C:\Users\xxxx\Documents\PerlProjects\Monks>perl commandloopX3.pl list of letters: adf list of letters: 123 list of letters: q

Replies are listed 'Best First'.
Re^5: $_ not set in while <>
by kcott (Bishop) on Jun 06, 2021 at 06:28 UTC

    G'day Marshall,

    I think the issue here is that the OP wrote "read a file", not "read from the keyboard". If the sentinel value is detected, then processing of the file should stop; however, I think it's reasonable to assume that if no sentinel value is detected, then processing of the file should stop at the end of the file.

    Note that in the examples below, I used a common alias of mine:

    $ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -MCarp::Always -E +'

    Here's a file that simulates your keyboard input. I've added an extra line that is to be ignored:

    $ cat > pm_11133571.dat 234 asdf quit ignore

    That is processed (almost) identically to your keyboard input:

    ken@titan ~/tmp $ perle 'my $line; while ( (print "list of letters: "),$line=<>, $line + !~ /\s*quit|exit|q\s*$/i) { print "doing something with $line\n"}' p +m_11133571.dat list of letters: doing something with 234 list of letters: doing something with asdf list of letters: ken@titan ~/tmp

    I said "almost" because, as you may have noticed, there's a dangling "list of letters: " prompt as the last line of output.

    However, if there's no sentinel value, processing does not stop at the end of the file; instead, the code is stuck in a loop. Also, warnings are emitted. Both of those things are what ++ikegami predicted.

    Consider this slightly different input file (without a sentinel):

    $ cat > pm_11133571_2.dat 234 asdf ignore

    Here's what happens:

    $ perle 'my $line; while ( (print "list of letters: "),$line=<>, $line + !~ /\s*quit|exit|q\s*$/i) { print "doing something with $line\n"}' p +m_11133571_2.dat list of letters: doing something with 234 list of letters: doing something with asdf list of letters: doing something with ignore Use of uninitialized value $line in pattern match (m//) at -e line 1, +<> line 3. at -e line 1, <ARGV> line 3. Use of uninitialized value $line in concatenation (.) or string at -e +line 1, <> line 3. at -e line 1, <ARGV> line 3. list of letters: doing something with list of letters:

    The screen output stopped there; I used Ctrl-C to get back to my shell prompt. Of course, I could've typed one of the sentinel values (quit|exit|q) but would you expect users to know what those values were; and even if they did, would you expect them to do this in the "production" environment you described.

    Update: I started to compose my response before your post had any updates. After posting, I see you've added three updates. That's not a complaint about the updates; just advice on what I was responding to.

    — Ken

      Oh, I see said the blind man to his deaf wife as he picked up his hammer and saw.

      I suspect that something very simple like this would work:

      use strict; use warnings; my $pattern ='ABC'; while (<>) { last if /$pattern/; } # processing of rest of file starts here... print "printing all lines after $pattern detected!\n"; while (<>) { print; }
Re^5: $_ not set in while <>
by ikegami (Pope) on Jun 09, 2021 at 05:57 UTC

    The condition is not "dense".

    I didn't say it was dense. What does that even mean? At what point does something become dense? How can you claim it is or isn't dense?

    I said the "condition is so dense you missed that it devolves into an infinite loop of prints and warns." You tried to jam so much into a single expression that you got the expression wrong. Worse, and maybe even more importantly, it's very hard to notice that it's wrong because it's so dense. I only noticed when I rewrote your code.

    Works fine for me

    How would you know? You didn't try giving EOF or an error. The fact that your code doesn't handle this immediately stood out after a rewrite.

    I am sure that there are many Monks who will disagree with style issues!

    Sure, but when it's so hard to read that errors crop in, and when the other alternative makes the error obvious, we start leaving the realm of subjectiveness and entering the realm of objectiveness.

    Also, it leaks the $line variable to the surrounding scope.

    Seeking work! You can reach me at ikegami@adaelis.com

      For those wondering:
      • Misunderstanding 1:

        dense:

        • Having relatively high density.
        • Slow to comprehend; of low intelligence.

      • Misunderstanding 2:
        Marshall was only attempting to read from the keyboard (and misunderstanding the OP)

        That's why he didn't care about checking defined for the line, since undef is a way to indicate EOF for files.

        But the special power of while(<>) is that he could call it on a file in @ARGV for testing those manual inputs

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        What are you talking about. We were both discussing density, and we were both talking about a terminal (or at least didn't exclude it).

        Perhaps you think a terminal can't return EOF? Yet that's a common occurrence. I didn't say those things you tried to put in my mouth cause I didn't mean those things.

        A program that fails to handle a common occurrence by going into an infinite loop is bad, and a style that makes this kind of error easy and hard to notice is not that great. Simple as that.

        Seeking work! You can reach me at ikegami@adaelis.com

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11133576]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (2)
As of 2021-10-16 12:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (69 votes). Check out past polls.

    Notices?