EDIT:
I use used bareword filehandles.
In the course of this discussion I was convinced not to do so.
I've seen many Perl programmers advocating the usage of lexical scalars instead. Though there are good reasons for this, it has a drawback. Filehandles in Perl are special on a syntactical level. The compiler is capable of catching errors like this:
open FH, '<', 'myfile'; print FH, "something\n";
by emitting an error:
No comma allowed after filehandle at ...
Whereas strange things happen at runtime if you use:
NB: Someone else pointed to this subtle difference but sadly I don't remember who and where it was. She/he should be credited here.open my $fh, '<', 'myfile'; print $fh, "something\n";
So I stay with barewords and try to avoid the problems caused by the usage of global variables using this idiom:
open local *FH, '<', 'myfile'; while (<FH>) { # do something } close FH;
Some features:
- usages of equally named file handles do not affect each other in different scopes
- the usage in a sub does no harm if the sub is in the same package and it uses the same idiom
- the usage in a sub of a different package does not harm.
The question remains: Do I miss something here? Do you see any pitfalls using this approach?
Here is an example demonstrating the issues I'm aware of.
#!/usr/bin/perl use Test2::V0; package Foobar; our $foobar = "foobar\n"; our @foobar; sub use_fh { # unlocalized use of FH in separate package open FH, '<', \$foobar; @foobar = <FH>; close FH; } package main; my $foo = "foo\n"; my $bar = "bar\n"; my $baz = "baz\n"; my @baz; sub use_localized_fh { # protect caller's FH open local *FH, '<', \$baz; @baz = <FH>; close FH; } sub close_fh { # unlocalized use of FH close FH; } # open now, use later open FH, '<', \$bar; my @foo; # create new scope { # use localized FH, protecting handle opened on \$bar open local *FH, '<', \$foo; # call sub that uses localized FH use_localized_fh; # call sub in other package that uses FH Foobar::use_fh; # FH still intact @foo = <FH>; close FH; } is \@baz, [$baz], 'got $baz in sub'; is \@Foobar::foobar, [$Foobar::foobar], 'got $Foobar::foobar in foreig +n sub'; is \@foo, [$foo], 'good: got $foo'; { open local *FH, '<', \$foo; # call sub that closes FH close_fh; @foo = <FH>; close FH; } is \@foo, [], 'bad: FH was closed in sub'; # FH at this scope is still untouched my @bar = <FH>; close FH; is \@bar, [$bar], 'good: got $bar'; done_testing;
Greetings,
-jo
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: lexical vs. local file handles
by haukex (Archbishop) on Apr 18, 2020 at 19:04 UTC | |
by jo37 (Deacon) on Apr 18, 2020 at 19:40 UTC | |
by haukex (Archbishop) on Apr 18, 2020 at 19:46 UTC | |
by jo37 (Deacon) on Apr 18, 2020 at 19:52 UTC | |
by chromatic (Archbishop) on Apr 18, 2020 at 20:52 UTC | |
by haukex (Archbishop) on Apr 18, 2020 at 19:54 UTC | |
| |
by haukex (Archbishop) on Apr 18, 2020 at 21:49 UTC | |
by jo37 (Deacon) on Apr 19, 2020 at 07:52 UTC | |
by haukex (Archbishop) on Apr 19, 2020 at 08:16 UTC | |
| |
Re: lexical vs. local file handles
by Your Mother (Archbishop) on Apr 18, 2020 at 23:36 UTC | |
by jo37 (Deacon) on Apr 19, 2020 at 07:54 UTC | |
Re: lexical vs. local file handles
by Anonymous Monk on Apr 18, 2020 at 21:37 UTC |