3

少し前に、私は質問をします:組み込みの Perl 関数を再定義するにはどうすればよいですか?

そして、答えは私に役立っています。Perl の「open」機能をオーバーライドして、ファイル アクセスをログに記録できるようにするパッケージがあります。

ここで、元のコードの機能を壊すケースに行き着きました。

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"

どうすれば修正できますか?

4

3 に答える 3

8

「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;

これらは、範囲外になると自己閉鎖するという点で非常に有益です。

于 2009-05-02T01:25:57.370 に答える
1

比較:

> 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」とは別の名前を使用しました。これは、組み込みのハンドルでない場合にのみ間接オブジェクトが間違っているように見えるためです。

于 2009-05-02T00:29:11.250 に答える
1

これは機能し、エラーは発生しません...

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

これにより、 「間接オブジェクト構文」が混乱するのを防ぎます

ただし、Perl で CHECK やその他の特別な名前付きコード ブロックを使用することは避けることをお勧めします。また、ファイルハンドルにレキシカル変数を使用することをお勧めします。PBP

于 2009-05-02T16:44:01.923 に答える