Re: Is there a problem with using barewords as filehandles ?
by hippo (Bishop) on Jul 01, 2020 at 09:57 UTC
|
My understanding is that the problem is with the lack of restricted scope. Bareword filehandles are essentially globalpackage scoped (thanks, LanX) so your RD could easily stomp on someone else's RD in a module which your code usesthe same package and vice-versa. These possibilities for action-at-a-distance are the downside.
Is there some official perl documentation about any such issue ?
Not that I'm aware of. There's an oblique mention in the FAQ which says "Since you want to be a good programmer, you probably want to use a lexical filehandle" but makes no mention of why good programmers want to use lexical filehandles.
Update: Just found this very interesting counterpoint where luminaries such as brian_d_foy and merlyn argue in favour of keeping them (almost a decade ago). The last point about strict is also interesting in the light of recent events.
See also:
| [reply] |
|
> Bareword filehandles are essentially global
Sorry for nitpicking but they are package variables not full globals.
Conflicts can be avoided with proper use of package directives.
Special variables are real globals, they are available everywhere but always belong to main:: package (IIRC)
| [reply] [d/l] |
|
| [reply] |
|
| [reply] |
|
|
|
A review of PBP which praises Damian's rationale without quoting it, alas
If you are really keen you might be able to read at least part of the rationale by searching via google books,
I just did that and here is some of Damian's rationale:
... using a bareword as a file handle causes Perl to store the corresponding input stream descriptor in the symbol table of the current package ... and if that symbol has already been used as a filehandle anywhere else in the same package, executing this open statement will close the previous file handle and replace it with the newly opened one ... bareword file handles are even more unreliable if there happens to be a subroutine of the same name currently in scope ...
For completeness, from Perl Best Practices
here are all Perl Best Practices that mention bareword or filehandle:
- 45. Don't use barewords.
- 125. Don't use bareword filehandles.
- 126. Use indirect filehandles.
- 127. If you have to use a package filehandle, localize it first.
- 130. Close filehandles explicitly, and as soon as possible.
- 133. Slurp a filehandle with a do block for purity.
- 136. Always put filehandles in braces within any print statement.
- 246. Don't tie variables or filehandles.
| [reply] |
|
As an example, one of my worst debugging sessions involved open's scope. Imagine you have a generic open_file() function in a script. The function uses a bareword FH, because whoever wrote it wasn't thinking about scope, they were just making sure a file was "open" (kinda related to the counterpoint you mentioned, that person might have learned enough to get by but not yet realize all the implications of what they were doing). Sometimes, deep in the code, you might open *another* file while processing the first one, leading to some bewildering action at a distince bugs...
| [reply] |
|
> because whoever wrote it wasn't thinking about scope,
FWIW you can localize a FH inside the function's scope, but this implies some glob syntax IIRC.
I think local *FH but ...
- I'd need to look it up
- it'll localize all other vars with the same symbol, like $FH too
- it's a dynamic runtime scope not a lexical, ie don't call another sub from inside which doesn't localize the same symbol before using it
Not that beginner friendly
| [reply] [d/l] |
Re: Is there a problem with using barewords as filehandles ?
by Discipulus (Canon) on Jul 01, 2020 at 10:19 UTC
|
Hello syphilis,
I imagine you already know why is better to use lexical filehandles with 3 arguments (enforcing the scope, autoclose,...), but as you are asking about official docs I cannot find anything. Well generally speaking perl documentation is very eterogenous in style. At least.
> What's so wrong with doing open RD, '<', 'file.txt' ?
Nothing if you know what happens in this line and in the whole code you are writing.
perl -we "use strict; open FH, '>', 'text.txt'; open FH, '>', 'text.tx
+t';"
perl -we "use strict; open my $fh, '>', 'text.txt'; open my $fh, '>',
+'text.txt';"
"my" variable $fh masks earlier declaration in same scope at -e line 1
+.
I consider the second line less error prone, if you have thousand lines of code with many open FH statements the risk to forget to close one of them and mess the whole thing is high.
So it is a matter of (better) habits and nothing wrong per se. See also why-the-modern-perl-book-avoids-bareword-filehandles. And perlmaven.
More: if it is a matter of good habits I will enforce an exception also in the 2 arguments form of open What happens if you feed open my $in, $filename; with >/etc/passwd ?
Infact 2 arguments form is dangeourous.
If it was my decision I will enhance strict pragma to deal with this:
use strict;
open FH, '<', 'filename'; # dies
open my $fh, 'filename'; # dies
no strict 'open';
open FH, '<', 'filename'; # now ok
open my $fh, 'filename'; # now ok
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] [select] |
|
| [reply] |
Re: Is there a problem with using barewords as filehandles ?
by LanX (Saint) on Jul 01, 2020 at 11:04 UTC
|
Apart from scoping/namespace rules...
The essential problem is that subs and FHs can't be distinguished.
In Perl 4 subs needed a & sigil, this was dropped in Perl 5 but no sigil was introduced for filehandles, so ambiguity was a consequence.
That's not only frustrating for users but must complicate maintenance of the parser.
Another problem is passing FH as arguments into subs.
Then newbies need to learn the whole typeglob technique with *FH.
| [reply] |
|
| [reply] |
Re: Is there a problem with using barewords as filehandles ?
by haukex (Archbishop) on Jul 01, 2020 at 19:39 UTC
|
What's so wrong with doing open RD, '<', 'file.txt' ?
I was involved with two discussions about this recently, lexical vs. local file handles and Re^2: Summing numbers in a file, so here are my two cents. To summarize the disadvantages of bareword filehandles:
- They don't protect against typos.
- They're package-globals.
- They clash with package names and subs.
- If you do want to localize them, that comes with even more disadvantages.
- Package-global filehandles usually go out of scope much later than lexicals, so the automatic close doesn't really help.
I don't think that bareword filehandles should "never, ever" be used, and removing them would most likely break a lot of CPAN. But IMHO they shouldn't be used in new code, and newcomers should use lexicals instead. My understanding of Perl 7 is that it is an attempt to introduce defaults that are modern and reduce the cognitive load on the coder - sure, you can use bareword filehandles if you know what you're doing and are willing to manually check for all potentially typos and name clashes caused by them. In the beginning, I used to code without strict and warnings, and I can still remember the amount of time I would spend proofreading my code for such issues.
use of barewords as filehandles will be disallowed in perl 7
My understanding of Sawyer's talk is that the new default will be no bareword::filehandles, and you are free to write use bareword::filehandles.
| [reply] [d/l] [select] |
|
.... you are free to write use bareword::filehandles
Thanks for pointing that out.
And thanks to everyone for all the additional relevant points and information.
I don't do much with perl filehandles, but when I do, I've generally used barewords.
I thought I would have made every dumb mistake that was possible with them, but I can see there are some mistakes that I hadn't encountered.
(I wonder if that implies that I'm actually smarter than I thought ;-)
Cheers, Rob
| [reply] |
Re: Is there a problem with using barewords as filehandles ? (updated link)
by LanX (Saint) on Jul 01, 2020 at 10:17 UTC
|
| [reply] [d/l] |
Re: Is there a problem with using barewords as filehandles ?
by eyepopslikeamosquito (Archbishop) on Jul 02, 2020 at 09:55 UTC
|
For completeness, good ol' merlyn's classic Perl Best Practices slideshare:
- 10.1 Filehandles (slide 136)
- 10.2 Indirect Filehandles (slide 137)
- 10.3 Localizing Filehandles (slide 138)
- 10.4 Opening Cleanly (slide 139)
gives some excellent advice:
- Don't use bareword filehandles: can't easily pass them around; can't easily localize them; can't make them "go out of scope".
- Use indirect filehandles: they close automatically; can be passed to/from subroutines; can be stored in aggregates; might need readline or print { } though - e.g. my $line = readline $inputs[3]; print { $output_for{$day} } @list;
- Localizing filehandles: if you must use a package filehandle localize it; local *HANDLE; beware this also stomps on other package items ... so use it sparingly ... that's why indirect handles are better.
- Opening cleanly: use IO::File or 3-arg open.
| [reply] [d/l] [select] |
Re: Is there a problem with using barewords as filehandles ?
by jcb (Parson) on Jul 02, 2020 at 03:49 UTC
|
Bareword filehandles have their places, particularly in simple scripts, where there really is almost no difference between them and lexical file handles — declaring a lexical at file-scope has almost exactly the same effect, and exactly the same effect if the convention of maintaining a 1:1 mapping between files and packages is followed.
However, a sub that opens a file and returns a handle should always return a lexical filehandle, unless its purpose is to return "THE" singleton filehandle for some resource, and in that case it should be using our to store the filehandle in a global. Generally, bareword filehandles should be limited to the mainline code in the top-level script. Subroutines should use lexical filehandles and modules should only contain subroutines.
In Perl, all "globals" are actually package variables, although a few special names (including the "punctuation variables") are forced into package main. The distinction is that a "global" variable is stored in a symbol table slot in some package. Package variables in Perl are globally-accessible, since the package namespace is itself global. The our keyword creates lexically-scoped aliases to package variables and is very convenient when needed.
A lexical declared at file scope is effectively a global variable and has all of the same problems in complex code, with the additional risk that file-scope lexicals can be shared across packages if multiple packages are defined in the same file. Global variables are generally dangerous in programming and I strongly favor the use of bareword filehandles at top-level in preference to declaring lexicals at file-scope and thinking that you are safe.
Perhaps the best would be to default to use bareword::filehandles in package main and no bareword::filehandles in other packages. This keeps the feature where it is most useful, to avoid the "head in sand" problem of using file-scope lexicals in the main script, while still pushing modules to avoid the feature unless it really is appropriate.
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
|
|
|
|
Re: Is there a problem with using barewords as filehandles ?
by syphilis (Archbishop) on Jul 18, 2020 at 04:03 UTC
|
use of barewords as filehandles will be disallowed in perl 7
Just a couple of additional questions:
When (if) bareword filehandles are disallowed, will we still be able to do:
print STDERR 'ok';
I thought this might have been touched on elsewhere in this thread, but I can't see it now. (Apologies if I've missed it.)
Also, if foo() is an XSub that takes a FILE* as its first argument, would I still be allowed to call it from perl with:
foo(*STDOUT, ....);
Maybe I should just wait and see what happens ?
Cheers, Rob
| [reply] [d/l] [select] |
|
When (if) bareword filehandles are disallowed, will we still be able to do: print STDERR 'ok';
If bareword::filehandles is anything to go by, then STDIN, STDOUT, STDERR, ARGV, ARGVOUT, and DATA would still be allowed.
| [reply] [d/l] [select] |
|
If bareword::filehandles is anything to go by ....
Aaah, yes - I'll take my cues from bareword::filehandles. Seems likely (even if not actually guaranteed) that this would be something we "can go by".
So far, so good - the changes I've made are working ok under use bareword::filehandles;
Thanks haukex.
Cheers, Rob
| [reply] [d/l] |
|
|
| [reply] [d/l] [select] |