Some say we should use a lexical filehandle instead of a typeglob, like this:
open $fh, $filename;
But most Perl books, including The Llama Book, use a typeglob, like this:
open LOGFILE, $filename;
So what are the differences? Which one is considered a better practice?
The earliest edition of the Llama Book is from 1993, before lexical filehandles were part of the Perl language. Lexical filehandles are a better practice for a variety of reasons. The most important disadvantages of typeglobs are
they are always global in scope, which can lead to insidious bugs like this one:
sub doSomething { my ($input) = @_; # let's compare $input to something we read from another file open(F, "<", $anotherFile); @F = <F>; close F; do_some_comparison($input, @F); } open(F, "<", $myfile); while (<F>) { doSomething($_); # do'h -- just closed the F filehandle } close F;
they are harder to pass to a subroutine than a lexical filehandle
package package1; sub log_time { # print timestamp to filehandle my ($fh) = @_; print $fh scalar localtime, "\n"; } package package2; open GLOB, '>', 'log1'; open $lexical, '>', 'log2'; package1::log_time($lexical); # works as expected package1::log_time(GLOB); # doesn't work package1::log_time('GLOB'); # doesn't work package1::log_time(*GLOB); # works package1::log_time(package2::GLOB); # works package1::log_time('package2::GLOB'); # works
See also: Why is three-argument open calls with autovivified filehandles a Perl best practice?
When lexical variables are used, the filehandles have the scope of these variables and are automatically closed whenever you leave that scope:
{
open my $fh, '<', 'file' or die $!;
# ...
# the fh is closed upon leaving the scope
}
So you do not create permanent global variables.
Lexical filehandles can be passed easily as arguments, filehandles cannot. Typeglobs can (or at least references to them can), but that's kinda messy. Consider sticking with lexical variables, and make sure to declare them first, so you know that they're really lexical and not local or global. I.e.
my $fh;
open $fh, $filename;
Also consider using IO::Handle
or IO::File
as options. Used to be FileHandle
but was informed by ysth below that FileHandle
now just uses 'IO::Handle' in turn, which is news to me since 5.6, but there's a lot to learn here. :-)
Also, don't forget use strict
:-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With