Какая из них является хорошей практикой, лексический дескриптор файла или глобус типа? - PullRequest
14 голосов
/ 18 июля 2010

Некоторые говорят, что мы должны использовать лексический дескриптор файла вместо typeglob, например:

open $fh, $filename;

Но большинство книг по Perl, включая The Llama Book , используют typeglob, например:

open LOGFILE, $filename;

Так в чем же различия?Какой из них считается лучшей практикой?

Ответы [ 4 ]

22 голосов
/ 18 июля 2010

Самое раннее издание Книги Ламы - с 1993 года, до того, как лексические дескрипторы файлов стали частью языка Perl. Лексические дескрипторы файлов - лучшая практика по ряду причин. Наиболее важными недостатками typeglobs являются

  1. они всегда глобальны по своему охвату, что может привести к таким коварным ошибкам, как этот:

    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. их сложнее передать подпрограмме, чем лексическому дескриптору файла

    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
    

См. Также: Почему открытые вызовы с тремя аргументами и автоматически возвращаемыми файловыми дескрипторами являются лучшей практикой Perl?

14 голосов
/ 18 июля 2010

Когда используются лексические переменные, дескрипторы файлов имеют область видимости этих переменных и автоматически закрываются при выходе из этой области:

{
   open my $fh, '<', 'file' or die $!;
   # ...
   # the fh is closed upon leaving the scope
}

То есть вы не создаете постоянные глобальные переменные.

8 голосов
/ 18 июля 2010

Лексические файловые дескрипторы могут быть легко переданы в качестве аргументов, файловые дескрипторы не могут. Typeglobs могут (или, по крайней мере, ссылки на них могут), но это немного грязно. Подумайте о том, чтобы придерживаться лексических переменных, и сначала обязательно объявите их, чтобы вы знали, что они действительно лексические, а не локальные или глобальные. * 1001 Т.е. *

my $fh;
open $fh, $filename;

Также рассмотрите возможность использования IO::Handle или IO::File в качестве параметров. Раньше был FileHandle, но ysth ниже сообщал, что FileHandle теперь просто использует IO :: Handle по очереди, что для меня новость с 5.6, но здесь есть чему поучиться : -)

Кроме того, не забудьте use strict: -)

1 голос
/ 01 июля 2015

Использование дескриптора файла typeglob не рекомендуется, потому что, если вы не обращаете внимания, это может привести к нескольким проблемам. Например: если вы создаете рекурсивную функцию, которая использует один и тот же глобус типа, вы получите некоторые предупреждения при попытке закрыть дескриптор файла, если не создадите ограниченный во времени глобус на основе пакета. Лексические переменные попадают в область, в которой они определены, в то время как область действия typeglob предназначена для полного пакета, в котором она определена.

Для резюме:

Если вы хотите остаться с дескриптором файла typeglob, обязательно создайте ограниченный во времени глобус на основе пакета:

...
local *FH;
open FH, '<', $filepath or die(sprintf('Could not open %s: %s', $filepath, $!));
...

иначе, используйте лексическую переменную

...
open my $fh, '<', $filepath or die(sprintf('Could not open %s: %s', $filepath, $!));
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...