Как правильно переопределить «open» в Perl? - PullRequest
3 голосов
/ 02 мая 2009

Некоторое время назад я задал вопрос: Как мне переопределить встроенные функции Perl?

И ответы послужили мне хорошо. У меня есть пакет, который переопределяет функцию open в Perl, позволяющую мне регистрировать доступ к файлам.

Теперь я подошел к случаю, который нарушает функциональность исходного кода.

use strict;
use warnings;
use Data::Dumper;

sub myopen (*;@) {
  my $p;
  my $retval = CORE::open($p, $_[1]);
  {
    no strict;
    *{"main::$_[0]"} = $p;
  }
  return $retval;
}

BEGIN {
  *CORE::GLOBAL::open = *myopen;
};

my @a = (1, 2, 3);

open(CHECK, ">dump") or print "UNABLE TO OPEN DUMPER FILE: $!\n";
print CHECK "test\n";
print CHECK Data::Dumper->Dump(\@a);
close CHECK

Теперь я получаю это сообщение:

Can't locate object method "CHECK" via package "Data::Dumper"

Как мне это исправить?

Ответы [ 3 ]

8 голосов
/ 02 мая 2009

Попробуйте использовать имя, отличное от "CHECK" .

«CHECK» - это специальная функция, которая вызывается во время компиляции, и вы действительно не должны ее использовать.

$ open CHECK , '<', 'foo.txt'; 
Took 0.00224494934082031 seconds.

Runtime error: Undefined subroutine &Devel::REPL::Plugin::Packages::DefaultScratchpad::CHECK called at (eval 329) line 5.

$ open CHECKS , '<', 'foo.txt'; 
Took 0.00155806541442871 seconds.

$

Почему именно эта ошибка?

perl -MO=Deparse -e 'print CHECK Data::Dumper 1';
print 'Data::Dumper'->CHECK(1);

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

используйте эту запись:

open my $fh, '<' , $foo ; 
print <$fh>;
close $fh;

Они особенно полезны, если они закрываются, когда выходят за рамки видимости.

1 голос
/ 02 мая 2009

Это будет работать и без выдачи ошибки ...

 print {*CHECK} Data::Dumper->Dump(\@a);

Это предотвращает путаницу, имеет "Синтаксис косвенного объекта"

Однако я рекомендую избегать использования CHECK и других специальных именованных блоков кода в Perl , и использование лексических переменных для файловых дескрипторов является предпочтительным методом. PBP

1 голос
/ 02 мая 2009

Сравнить:

> perl -MData::Dumper -e'local*_=*STDOUT;print _ Data::Dumper->Dump([2]);'
Can't locate object method "_" via package "Data::Dumper" at -e line 1.

до

> perl -MData::Dumper -e'local*_=*STDOUT;print _ ( Data::Dumper->Dump([2]) );'
$VAR1 = 2;

Я использовал имя, отличное от «STDOUT», потому что кажется, что косвенный объект ошибается только тогда, когда это не встроенный дескриптор.

...