Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which one is good practice, a lexical filehandle or a typeglob?

Tags:

perl

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?

like image 515
powerboy Avatar asked Jul 18 '10 18:07

powerboy


3 Answers

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: Why is three-argument open calls with autovivified filehandles a Perl best practice?

like image 173
mob Avatar answered Nov 15 '22 19:11

mob


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.

like image 33
Eugene Yarmash Avatar answered Nov 15 '22 20:11

Eugene Yarmash


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

like image 25
eruciform Avatar answered Nov 15 '22 19:11

eruciform