develooper Front page | perl.perl5.porters | Postings from July 2008

Re: Creative and *routine* use of so-called

Thread Next
Ed Avis
July 29, 2008 16:20
Re: Creative and *routine* use of so-called
Message ID:
om Christiansen <tchrist <at>> writes:

>>But if you think this is an important issue, wouldn't it make much
>>more sense to teach people RIGHT NOW that they shouldn't rely on
>>while (<>) automatically open files for them,

>Because while you can lead a horse to water, but you can't make it drink.
>And if you let it drink freely on its own, it may drink itself to death.
>Which just shows that you can't win for trying.
>I spent years on it--YEARS.  They still just won't learn.  Things
>like this have been in the FAQ since BEFORE Camel-1 even; they've
>been in plenty of the available documentation since then--

[illustrative examples of how the documentation has deteriorated snipped]

You are certainly right that you've spent a lot of effort on this and
other aspects of the perl documentation, which is greatly appreciated
BTW, and that it was probably clearer in older versions.

But isn't all this effort on documenting the caveats and gotchas of
<>, with only moderate success in educating the perl-using public, an
indicator that it might be better to step back and think of a better
way of doing it?  The mere fact that <> requires so much documentation
and controversy, and arguments about when it is safe to use and when
it isn't, and discussions about exactly the right incantation to add
\0 to the end of your filenames, surely shows that its semantics are
a bit hairy at the very least: too hairy for such a simple-looking
operator that everyone uses without a second thought.

(Of course, whatever warning appears under 'open' also needs to be
duplicated under <>, since it is by no means obvious that <> is using
the magical open internally.)

Why not fix <> so it doesn't need all the explanation?  Make it just
read the files, which can be adequately documented in one sentence.
And add a new operator, just a couple of characters longer, that
people can use to get all the handy magic behaviour, *if they want it*
and having read the documentation.

If the magic is separated out into a separate operator then all the
elaborate discussion of what can go wrong and how to change $_ to
<./$_\0 is no longer necessary; just note that <<>> reads
ordinarily-named filenames but is not guaranteed to do that all the
time, and if you just want to read files use <>.  No need to spend
years trying to undo the effects of perlfaq editors and careless
tutorial writers!  Documentation effort (and indeed mailing list
bandwidth) can be spent on something more useful.

>Which brings me to my final complaint of the day.

>    % perl -i.orig -pe 'print "this is more stuff\n"' it
>    % echo $?
>    0
>    % ls -l it*
>    0 -rw-r--r--  1 tchrist  wheel  0 Jul 29 15:05 it
>    0 -rw-r--r--  1 tchrist  wheel  0 Jul 29 14:06 it.orig
>To this day, Perl's implicit closing of files doesn't warn you of
>errors, let alone exit nonzero.  This makes it do wrong thing and not
>even tell you it did them wrong.

I am glad you mentioned this, because I also think it's a pretty
egregious bug, but I was rather imagining you'd come out to defend it,
point out that it has always been that way and why change it now, and
anyway is clearly mentioned as a note to an addendum to a particular
perlfaq answer.  I am glad we agree on this issue at least :-(.

>This is a *true* problem, because checking for the success of print()
>is neither necessary nor sufficient to detect the success of print().

It is not sufficient; I think it might sometimes be necessary, see

Since nobody in practice checks the return status of every print()
call, I would like to see an enhancement to perl where if any print()
on a filehandle fails, it sets a flag which is then checked by
close().  So you could be sure to catch file I/O errors sooner or
later, if not immediately.  But that is for another thread ;-p.

>I've never convinced anybody this is important.  Since *every*
>program should do this for correctness, it has to be in the run-time
>system to avoid it ever being forgotten.

Exactly!  It's no use expecting the programmer to put in some extra
verbiage to make the code correct, especially when none of the
examples or tutorials do it.  Make it do the non-surprising thing by
default, and if someone wants to turn error checking *off*, they can
use some syntax for that, after finding out about it (and its possible
dangers) in the documentation.

>Sure, there's stuff like this you can do:
>     END { close(STDOUT) || die "can't close stdout: $!" }

Is even that sufficient?  Is it not possible a print() might fail but
the next print() succeed (perhaps the disk was full, but then some
space became available) and the error flag gets cleared?  Does it
depend on whether stdout is opened to a file, a pipe, a tty, etc?

[further example of incorrect behaviour]

>| Notice how even my cat is smarter than your perl!? :( |

I would also note that cat has absolutely no problem handing arbitrary
filenames, be they >>>LOL<<<, |^^|, or anything else.  The only
exception is the standard Unix convention of - for stdin.

Of course, a perl filter program can be made to work with all possible
filenames if you write the code longhand instead of with <>, and it
can be made to handle file I/O robustly if you take the trouble to do
open and close by hand and check everything scrupulously.  But you
shouldn't have to.  The default should just work and be the safe,
checked code unless you specify otherwise.

>I firmly believe that this needs to be a part of *EVERY* Perl
>program, which consequently means it should *not* be there, but in
>the core itself:
>    END { close(STDOUT) || die "can't close stdout: $!" }

Yup, and also for STDERR (if closing STDERR fails you can attempt to
print a warning message to it, which might or might not get through,
but you can at least exit with nonzero status).

>Furthermore, I also believe all *IMPLICIT* closes that fail need to
>generate a mandatory io warning,

This also makes perfect sense.  Does anyone really object to this?  In
principle it is a backwards incompatible change (code that previously
chugged along without visible problems will now start producing
warnings or exiting with nonzero status) but I can't see the point of
taking compatibility to such extremes.

Ed Avis <>

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About