Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

truth in while condition

by TISON (Acolyte)
on Sep 30, 2018 at 10:54 UTC ( [id://1223317]=perlquestion: print w/replies, xml ) Need Help??

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

Hi guys, I have a script and an input file.
# script while ( $_ = <STDIN> ) { print; }
#input 42 0 1042
and the I run perl script < input and expect it should exit after read "0", but the script print "42\n0\n1024\n". When $_ = <STDIN> read "0", isn't it evals to a false value and then exit?

Replies are listed 'Best First'.
Re: truth in while condition
by LanX (Saint) on Sep 30, 2018 at 10:56 UTC
    No while is magic, please check the Perldoc in perlsyn.

    > If the condition expression of a while statement is based on any of a group of iterative expression types then it gets some magic treatment. The affected iterative expression types are readline, the<FILEHANDLE> input operator,readdir, glob, the <PATTERN>globbing operator, and each. If the condition expression is one of these expression types, then the value yielded by the iterative operator will be implicitly assigned to $_. If the condition expression is one of these expression types or an explicit assignment of one of them to a scalar, then the condition actually tests for definedness of the expression's value, not for its regular truth value.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        Yeah I took it from .Pl because my old mobile isn't up to date on certificates and is blocked from Perl.org.

        Honestly I was surprised about the new detailed explanation

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Even if it wasn't magical, it still wouldn't stop at that line. The two-character string being returned, 0␊, is true. The magic only matters when the last line of the file consists of a 0 without a terminating Line Feed. (It could also happen when $/ = \1;.)

      (Oops, the main point of this has already been mentioned a couple of times below, though this post still brings in new information.)

        (solved, see update)

        > (It could also happen when $/ = \1; )

        This splits on single characters, including \n.

        But I couldn't find this behavior documented, neither in perlvar#$INPUT_RECORD_SEPARATOR nor readline

        use strict; use warnings; use feature 'say'; $/ = \1; while ( $_= <DATA>) { say "<$_>"; } __DATA__ 1 0 345

        --->

        <1> < > <0> < > <3> <4> <5> < >

        update

        oops I misread \1 as "\1" (ASCII 01), but it's a ref to literal 1, so this from perlvar applies:

        > Setting $/ to a reference to an integer, scalar containing an integer, or scalar that's convertible to an integer will attempt to read records instead of lines, with the maximum record size being the referenced integer number of characters.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Thank you very much!
Re: truth in while condition
by johngg (Canon) on Sep 30, 2018 at 11:19 UTC

    You haven't chomped the newline.

    johngg@shiraz:~/perl/Monks$ perl -E ' $_ = qq{0\n}; say $_ ? q{True} : q{False}; chomp; say $_ ? q{True} : q{False};' True False

    Cheers,

    JohnGG

      Thanks for your reply! Sounds reasonable but what do you think about comment by LanX? It seems they are technically different.
        Both are right, but it's a bit tricky to construct a while-condition doing a readline and exiting at false.

        I'd rather use an explicit last with condition inside the body.

        use strict; use warnings; use feature 'say'; while ( $_= <DATA>, chomp, $_) { say; } __DATA__ 3 1 0 2
        -->
        3 1

        (NB: Iterators don't necessarily loop over lines where they need to chomp, <update see here>)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: truth in while condition (updated)
by AnomalousMonk (Archbishop) on Sep 30, 2018 at 18:40 UTC

    Truthiness is also discussed in Truth and Falsehood in perlsyn. As has been pointed out by others, you were testing "0\n" in the while-loop conditional and not the truly false string "0".

    Update: At last, I see the point first made by LanX here: even if  <STDIN> managed to return a plain, nominally false  "0" character, the loop would still execute because  "0" is defined and the special-case while-loop is conditional upon defined-ness! Thanks to BillKSmith (here) and LanX (here) for helping the scales to fall from my eyes.


    Give a man a fish:  <%-{-{-{-<

      > you were testing "0\n" in the while-loop conditional and not the truly false string "0".

      The following iterator returns no "\n" but still fails to stop at "truly false" number 0.

      see explanation here

      use strict; use warnings; use feature 'say'; my $i = Iterator->new([1,0,2,undef,3]); while ( <$i> ) { say "<$_>"; } package Iterator; use overload '<>' => sub { shift @{$_[0]} }; sub new { my ($class,$obj) =@_; bless $obj, $class; }

      -->

      <1> <0> <2>

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      The reference in the first reply LanX explains that in this case, 'while' tests 'definedness' not 'Truthiness'.
      Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1223317]
Approved by marto
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-23 16:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found