4

私はレガシーコードを扱っておりrequire、 sub を定義する .pl ファイルが必要ですfoo。私の問題は、main::名前空間に既に別の sub がfooあり、現在扱っていないプログラムの一部で後で呼び出されることです。

私が必要とするファイルsub foo {}は、通常呼び出される場所で foo が発生することを明らかに望んでいないため、定義します。私の場合、それは悪いことです。

私は*fooグロブをいじってみました:

*old_foo = *foo;
require 'foo_killer.pl';
*foo = *old_foo;

もちろん、エイリアスを作成しただけなので (Brian d foy がMastering Perlの 133 ページで指摘しているように) *old_foo、現在は「空の」サブルーチンを指すため、これは機能しません。

*foo{CODE}エイリアシングする代わりに、何か別の場所にコピーする方法はありますか? それとも、これを解決するための別のアプローチがありますか?

4

3 に答える 3

3

自分でそれを理解しました。CODE型グロブ全体を別の型グロブに割り当てるのではなく、型グロブの一部を使用する必要があります。このように、コピーを作成するようです。

*old_foo = *foo{CODE};
require 'foo_killer.pl';
*foo = *old_foo{CODE};

brian d foy はMastering Perl (131f ページ) でもこれについて述べていますが、コピー部分については言及していません。

于 2012-10-01T09:20:10.983 に答える
3

このようにしてみてください

{
    local *foo;
    require 'foo_killer.pl';
}
于 2012-10-01T18:42:33.040 に答える
2

邪悪なレガシー コードをパッケージにまとめることをお勧めします。

package Foo;
use strict; 
use warnings;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(foo bar $evil $global $variables);

do "foo_killer.pl"
     or die "Failed to load foo_killer.pl: ".($@ || $!);
1;

コードが他の場所で必要な場合は何もしないdoため、ここでは を使用します。require(これのせいで醜いrequire "//path/to/code.pl"!)

このようにして、 またはfooを介し​​てロードするかどうかを決定できます。use Foo qw(foo);use Foo qw(bar);

更新:ああ、パスをfoo_killer.pl相対的に計算__FILE__し、絶対パスでロードしない方がよいでしょう:

my $foo_killer = __FILE__; # $LIB/Foo.pm
$foo_killer =~ s,(/+[^/]+),legacy,; # $LIB/legacy
$foo_killer .= "foo_killer.pl"; # $LIB/legacy/foo_killer.pl
# now do $foo_killer;

ただし、それはあなた(およびあなたのチーム)次第です。

于 2012-10-01T10:32:03.157 に答える