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.
| [reply] |
|
| [reply] |
|
| [reply] |
|
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.)
| [reply] [d/l] [select] |
|
(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.
| [reply] [d/l] [select] |
|
| [reply] |
Re: truth in while condition
by johngg (Canon) on Sep 30, 2018 at 11:19 UTC
|
johngg@shiraz:~/perl/Monks$ perl -E '
$_ = qq{0\n};
say $_ ? q{True} : q{False};
chomp;
say $_ ? q{True} : q{False};'
True
False
| [reply] [d/l] |
|
Thanks for your reply! Sounds reasonable but what do you think about comment by LanX? It seems they are technically different.
| [reply] |
|
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>)
| [reply] [d/l] [select] |
|
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: <%-{-{-{-<
| [reply] [d/l] [select] |
|
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>
| [reply] [d/l] [select] |
|
The reference in the first reply LanX explains that in this case, 'while' tests 'definedness' not 'Truthiness'.
| [reply] |