Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: $_ not set in while <>

by LanX (Sage)
on Jun 06, 2021 at 00:57 UTC ( #11133572=note: print w/replies, xml ) Need Help??


in reply to $_ not set in while <>

while(EXPR) has special magic for <> aka readline, but only if it's the sole EXPR. °

    while (<>) {

is a shorthand for

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

Personally I'd write

while (<>) { last if /pattern/; ... }

I find this more readable. YMMV!

HTH :)

update

B::Deparse can help you explore the difference

C:\>perl -MO=Deparse -e"while (<>) {}" while (defined($_ = readline ARGV)) { (); } -e syntax OK C:\>perl -MO=Deparse -e"while (<> and !/pattern/) {}" while (readline ARGV and not /pattern/) { (); } -e syntax OK C:\>

update

°)

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

Replies are listed 'Best First'.
Re^2: $_ not set in while <>
by Marshall (Canon) on Jun 06, 2021 at 02:59 UTC
    I disagree with your recommended code, but not your data.

    For a while loop, I like to write the main exit condition into the while statement. There could be many ways for the loop to exit past the main, expected condition. However, I code the "most likely" case into the conditional statement.

    Example:

    my $line; while ( (print "list of letters: "),$line=<>, $line !~ /\s*quit|exit|q +\s*$/i) {..do something with this line...}
    In the above, a "my" variable cannot be defined and be used within the same comma statement or logical "and" statement, hence the "my $line;" before the loop conditional.

    I do recommend using named variables for all while loops that go into production code.

    In the above, using "and" instead of the "," would be just fine. The truthfulness of a comma statement only has to do with the value of the last part.

      You seem to believe that the OP wants to read manual input from STDIN², but - as kcott noted - the OP said files.

      Please note that an empty diamond <> defaults to <ARGV> .

      And ARGV only defaults to "-" ° if the array @ARGV is empty.

      So if you want to read from STDIN, better say so explicitly by writing <STDIN> .

      from perlop

      Input from <> comes either from standard input, or from each file listed on the command line. Here's how it works: the first time <> is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-", which when opened gives you standard input. The @ARGV array is then processed as a list of filenames. The loop
      while (<>) { ... # code for each line }
      is equivalent to the following Perl-like pseudo code:
      unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }
      except that it isn't so cumbersome to say, and will actually work. It really does shift the @ARGV array and put the current filename into the $ARGV variable. It also uses filehandle ARGV internally. <> is just a synonym for <ARGV>, which is magical. (The pseudo code above doesn't work because it treats <ARGV> as non-magical.)

      NB: took me a while to find this, IMHO this should be at least mentioned/referenced in @ARGV

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

      °) IIRC "-" is just an alias for STDIN which can be passed literally as argument at the command line

      ²) STDIN is not necessarily the keyboard, it depends how the program was started

      That condition is so dense you missed that it devolves into an infinite loop of prints and warns. Fixed:

      while (1) { print "list of letters: "; defined( my $line = <> ) or last; $line !~ /\s*quit|exit|q\s*$/i or last; # Do something with $line. }

      Update: Added missing my.

        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
      Hi

      > In the above, a "my" variable cannot be defined and be used within the same comma statement or logical "and" statement, hence the "my $line;" before the loop conditional.

      In that case I'd prefer the c-style for(;;) loop ...

      update

      from https://perldoc.perl.org/perlsyn#For-Loops plus added my logic

        for (my $i = 1; $i < 10; $i++) { ... }
        is the same as this:
        { my $i = 1; while ($i < 10) { ... } continue { $i++; } }

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

      Respectfully dissenting here ... I find last if(s) to be quite useful, because you can quite easily have as many of them as you like. Even if (as is quite usually the case ...) the actual "while condition" is a dummy, the series of last if statements which immediately follow it spell-out every one of the possible "exit conditions," one at a time, separately.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (1)
As of 2021-10-23 02:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (86 votes). Check out past polls.

    Notices?