tags:

views:

107

answers:

3

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?

+5  A: 

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 :-)

eruciform
`open my $fh, ...` is perfectly legal (and in fact it's the usual idiom). No need for two lines.
hobbs
@hobbs - you're correct, i'm just pointing out that it might be something other than a lexical variable - it might have been a local or global ahead of time.
eruciform
FileHandle is deprecated.
ysth
@ysth: what's the newest incarnation of FileHandle? i haven't used perl extensively since like 5.6...
eruciform
@eruciform: IO::File, IO::Handle, etc. (which FileHandle itself now uses)
ysth
@ysth: cool, good advice. answer updated. :-)
eruciform
+8  A: 

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.

eugene y
+1 for automatic closing mention :-)
eruciform
+12  A: 

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

  1. 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;
    
  2. 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: http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice

mobrule
Very useful explanations! I read the Llama Book 5th Edition which is published in 2008. It still uses typeglobs.
powerboy
+1: good example
eruciform
`package1::log_time(\*GLOB); # works`
ysth