Perl inconsistency

M

Mike Mimic

Hi!

I think that I found some inconsistency in Perl.

Let us suppose we have a file named "file.txt" that contains
only one byte which is '0' (ASCII character for number 0).

And we execute this code:

open(FILE, '<file.txt');
if (<FILE>) {
print "OK\n";
}
close(FILE);

And code does not output anything. What is correct as "0" is
false in Perl.

But then we try this:

open(FILE, '<file.txt');
while (<FILE>) {
print "OK\n";
}
close(FILE);

And code do output "OK". What is strange. Becasue "0" is still
false. In "Programming Perl" it is written:

The while statement repeatedly executes the block as long as EXPR is true.

But "0" is false.

So what is going on?


Mike
 
B

Bill

Mike said:
Hi!

I think that I found some inconsistency in Perl.

Let us suppose we have a file named "file.txt" that contains
only one byte which is '0' (ASCII character for number 0).

And we execute this code:

open(FILE, '<file.txt');
if (<FILE>) {
print "OK\n";
}
close(FILE);

And code does not output anything. What is correct as "0" is
false in Perl.

But then we try this:

open(FILE, '<file.txt');
while (<FILE>) {
print "OK\n";
}
close(FILE);

And code do output "OK". What is strange. Becasue "0" is still
false. In "Programming Perl" it is written:

The while statement repeatedly executes the block as long as EXPR is true.

But "0" is false.

So what is going on?


Mike

IMO the second (<FILE>) looks line an array with one element containing
0 to Perl. It only becomes a scalar later. This is bacause <FILE> is
preferred to be an array of lines to Perl. Consider:

open(FILE, '<file.txt');
while (<FILE>) {
print "OK 1\n";
}
close(FILE);

open(FILE, '<file.txt');
while (scalar <FILE>) {
print "OK 2\n";
}
close(FILE);
 
B

Bob Walton

Mike said:
Hi!

I think that I found some inconsistency in Perl.

Let us suppose we have a file named "file.txt" that contains
only one byte which is '0' (ASCII character for number 0).

And we execute this code:

open(FILE, '<file.txt');
if (<FILE>) {
print "OK\n";
}
close(FILE);

And code does not output anything. What is correct as "0" is
false in Perl.

But then we try this:

open(FILE, '<file.txt');
while (<FILE>) {
print "OK\n";
}
close(FILE);

And code do output "OK". What is strange. Becasue "0" is still
false. In "Programming Perl" it is written:

The while loop with a <FH> operator is special, at least in recent
versions of Perl. It is actually interpreted as something like:

while(defined($_=<FH>)){
#...
}

See:

perldoc perlop

particularly the section titled "I/O Operators".
The while statement repeatedly executes the block as long as EXPR is true.

So it actually executes as long as the result is *defined*, not true.
<FH> gives undefined upon end of file, and is defined otherwise. Note
that this behavior is only true of the while loop (and "for(;<FH>;)" if
you want to be persnickety). It does not apply to other uses of the
<FH> operator. That feature (hack?) was put in to avoid having to code
the call to defined() over and over again to avoid the situation with
reading lines which evaluate to false which you mention. That makes
sense, as one almost never wants to stop reading when a false line
occurs, but rather when end of file occurs.
 
T

Tad McClellan

Bill said:
Mike Mimic wrote:


You should always, yes *always*, check the return value from open():

open(FILE, '<file.txt') or die "could not open 'file.txt' $!";

IMO the second (<FILE>) looks line an array
^^^^^ ^^^^^

Where is the at-sign then?

An "array" and a "list" are NOT the same thing. There is a FAQ about this...

(but there is no "list" there either.)

with one element containing
0 to Perl. It only becomes a scalar later.


If it exists, as in "element", then it has _already_ become a scalar value.

This is bacause <FILE> is
preferred to be an array of lines to Perl.


No it isn't. Where did you get that idea?



Your "O" is way off.

Invoking opinion when discussing machines is the exception
rather than the rule.
 
B

Bill

Tad said:
You should always, yes *always*, check the return value from open():

open(FILE, '<file.txt') or die "could not open 'file.txt' $!";




^^^^^ ^^^^^

Where is the at-sign then?

An "array" and a "list" are NOT the same thing. There is a FAQ about this...

(but there is no "list" there either.)






If it exists, as in "element", then it has _already_ become a scalar value.






No it isn't. Where did you get that idea?



Your "O" is way off.

Invoking opinion when discussing machines is the exception
rather than the rule.
Sorry, my bad. The "scalar" transform is of a boolean not an array. I
canceled the message after a minute, but the thing slipped through
anyway :(.
 
B

Bill

Bob said:
The while loop with a <FH> operator is special, at least in recent
versions of Perl. It is actually interpreted as something like:

while(defined($_=<FH>)){
#...
}

See:

perldoc perlop

particularly the section titled "I/O Operators".



So it actually executes as long as the result is *defined*, not true.
<FH> gives undefined upon end of file, and is defined otherwise. Note
that this behavior is only true of the while loop (and "for(;<FH>;)" if
you want to be persnickety). It does not apply to other uses of the
<FH> operator. That feature (hack?) was put in to avoid having to code
the call to defined() over and over again to avoid the situation with
reading lines which evaluate to false which you mention. That makes
sense, as one almost never wants to stop reading when a false line
occurs, but rather when end of file occurs.

Yes, that's perlop. But what about the below? There is some interpretive
DWIM magic here with context that is a bit beyond what can be expressed
in mere Perl code in the perldocs, I think :).

#!/usr/bin/perl

use strict;
use warnings;

# 'file.txt' contains just the character 0

open(FILE, '<file.txt');
while (<FILE>) {
print "OK 1\n";
}
close(FILE);

open(FILE, '<file.txt');
while (scalar <FILE>) {
print "OK 2\n";
}
close(FILE);

open(FILE, '<file.txt');
while( defined($_= <FILE>) ) {
print "OK 3\n";
}
close(FILE);

open(FILE, '<file.txt');
while (scalar defined($_= <FILE>)) {
print "OK 4\n";
}
close(FILE);

==========
prints:
OK 1
OK 3
OK 4
 
A

Anno Siegel

["while ( said:
Yes, that's perlop. But what about the below? There is some interpretive
DWIM magic here with context that is a bit beyond what can be expressed
in mere Perl code in the perldocs, I think :).

What's the big surprise? The behavior you show below is completely
and precisely predictable from the doc.

[The file is supposed to contain only one "0" (no linefeed)]
#!/usr/bin/perl

use strict;
use warnings;

# 'file.txt' contains just the character 0

open(FILE, '<file.txt');
while (<FILE>) {
print "OK 1\n";
}
close(FILE);

The standard case. Implicitly, defined() is applied, so this prints.

open(FILE, '<file.txt');
while (scalar <FILE>) {
print "OK 2\n";
}
close(FILE);

Not the standard case. No implicit application of defined() so no print.

open(FILE, '<file.txt');
while( defined($_= <FILE>) ) {
print "OK 3\n";
}
close(FILE);

This is explicitly what Perl does implicitly in the first case. Same
behavior, so it prints.

open(FILE, '<file.txt');
while (scalar defined($_= <FILE>)) {
print "OK 4\n";
}

"scalar defined(...)" is bogus. The defined() function is not context-
sensitive, it returns the same thing in any context. Besides, the
content of a while-condition is already in scalar context. So the
behavior is like the last one, it prints.

==========
prints:
OK 1
OK 3
OK 4

Sure. What did you expect?

Anno
 
M

Michele Dondi

I think that I found some inconsistency in Perl.

And who said Perl is supposed to be consistent? Others have explained
you precisely what's going on: the point is that dwimmeries are
thought to be friendly to you in the vast majority of cases. Though
the drawback is that you should be aware of them or either be prepared
to get burnt in the minority of cases in which they won't DWYM...

BTW: this is one of the reasons why Perl6 is being designed to be more
consistent (and IMHO *slightly* less magic).


Michele
 
1

187

Michele said:
[...]
BTW: this is one of the reasons why Perl6 is being designed to be more
consistent (and IMHO *slightly* less magic).

Hmm... isn't that going to defeat some (if not a great deal) of the
uefulness and greatness of Perl? I, like many other Perl lovers, love
Perl *becuase* of this usefulness and "magic" :)

If you want any form of consistency, it's in *how* you use a particular
piece of code/expression. Understanding how to get something to return
something in a particular way has always seemed to be a huge part of
Perl and once someone nails this, the rest of Perl is, for the most
part, a walk in the park :) (IMHO, the "magic", along with matering
RegEx, are the foundation of what makes Perl ($so = 'd.a.m.n.e.d') =~
s!\.!!g;#reat and useful! :)
 
M

Mike Mimic

Hi!

Michele said:
BTW: this is one of the reasons why Perl6 is being designed to be more
consistent (and IMHO *slightly* less magic).

It is nice to know that. Then I am waiting with impatience for Perl 6,
because I like that things are consistent (so that there are no special
cases which are that way just because they are special). If things
are not consistent you have to remember all special cases and this is
like learning irregular verbs. :)

But it is interesting that if you try this:

open(FILE, '<file.txt');
if ($_ = <FILE>) {
print "$_\n";
}
close(FILE);

Perl complains with:

Value of <HANDLE> construct can be "0"; test with defined()

And the same could be with while(<HANDLE>).


Mike
 
U

Uri Guttman

MM> But it is interesting that if you try this:

MM> open(FILE, '<file.txt');
MM> if ($_ = <FILE>) {
MM> print "$_\n";
MM> }
MM> close(FILE);

MM> Perl complains with:

MM> Value of <HANDLE> construct can be "0"; test with defined()

because that is not handled as a special case.

MM> And the same could be with while(<HANDLE>).

there is no warning because while is special cased for that. you have to
look at the history of this feature as it has changed several times over
the years. originally nothing was done and you had to do an explicit
defined check in a while(<>). later a warning was added if you didn't
check and finally the defined was implicitly added. that may not be a
totally accurate description of the history but it is close enough. so
stop whining about consistancy. perl has never been consistant nor will
perl6 fix all of that. it will still be perl and still DWIM in many
place that will make life easier for perl hackers and annoy others who
don't get it.

uri
 
A

Ala Qumsieh

Mike said:
But it is interesting that if you try this:

open(FILE, '<file.txt');
if ($_ = <FILE>) {
print "$_\n";
}
close(FILE);

Perl complains with:

Value of <HANDLE> construct can be "0"; test with defined()

And the same could be with while(<HANDLE>).

No. Please don't! Perl's (other) motto is to keep simple things simple
and hard things possible.

I would venture to guess that

if ($_ = <FILE>)

is not very useful, and a very tiny percentage of programs need it. The
other case:

while (<FILE>)

is ubiquitous and is a standard way of reading a file. I would really
hate it if I had to do:

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

DWIMery is one of the best things in Perl. Widely used idioms should be
simple and straight forward. Weirder idioms should be possible.

--Ala
 
M

Michele Dondi

perl6 fix all of that. it will still be perl and still DWIM in many

I totally agree! That is my impression too...
place that will make life easier for perl hackers and annoy others who
don't get it.

Well, it is my understantment (probably very limited in many different
ways, I must admit!) that Perl6's dwimmeries will be to a large extent
a consequence of how many "standard" objects evaluate in certain
contexts[*] rather than ad-hoc magic. Which is fine, IMHO.

Don't misunderstand me: there are some things I do not like about
Perl6, as of what is known about it, just like everyone else. But on
the complex these are overwhelmed by the ones I like, and I'm eager to
see the beast alive!!

In this sense I slightly regret having written that cmt at all, for I
may have conveyed a wrong impression to other people, although less
knowledgeable than you are, unfortunately, so that they may be
misleaded by my words...


[*] There was some discussion about this issue with split() as a topic
example. Similarly, on the p6l list a poster complained about the fact
that reverse() would break laziness on ranges (thus resulting in
inefficient code), to which Larry replied that this is not necessarily
the case provided that the range object is smart enough to handle it,
and there is no reason why it shouldn't be!
But then *you* probably already know this, and have a deeper
understanding of it than I have...


Michele
 
M

Michele Dondi

^^^^ ^^^^^^^^^^
^^^^ ^^^^^^^^^^
Hmm... isn't that going to defeat some (if not a great deal) of the
uefulness and greatness of Perl? I, like many other Perl lovers, love
Perl *becuase* of this usefulness and "magic" :)

Please, take my words with a grain of salt, especially taking into
account the two expressions above, that I (thought to have) stressed
from the start...

First it is only a personal impression, and secondarily I said only
"*slightly* less magic": OTOH it will be *much* more consistent,
powerful and rich of features in so many different ways that is almost
difficult to think of some them! So no: it won't be any less useful
than Perl5 is. And it can only be greater... of course it will take
some time to get accustomed with it. But then you'll still love it,
believe me!


Michele
 
M

Michele Dondi

It is nice to know that. Then I am waiting with impatience for Perl 6,
because I like that things are consistent (so that there are no special
cases which are that way just because they are special). If things
are not consistent you have to remember all special cases and this is
like learning irregular verbs. :)

Don't misunderstand me either, just like the other poster did (albeit
"on the other side")! Don't expect Perl6 to be any "simpler" (for some
meaning of "simple" you seem to have in mind) than Perl5 is. Just like
Perl5 you will be allowed to use in a simple minded way, but to get
the best of it you will still have to "learn many irregular verbs",
only that they won't be really irregular (or at least much less so!)


Michele
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top