4

我正在使用遗留代码,并且必须使用require定义 sub 的 .pl 文件foo。我的问题是在我的main::命名空间中已经有另一个 sub foo,稍后在我目前不处理的程序的一部分中调用它。

我需要定义的文件,sub foo {}因为显然它不希望 foo 的事情发生在它通常被调用的地方。就我而言,这很糟糕。

我尝试过使用*fooglob:

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

当然,这不起作用,因为我只创建了一个别名(正如 brian d foy 在Mastering Perl的第 133 页上指出的那样),因此*old_foo将指向现在的“空”子例程。

有没有办法以某种方式将其中的内容复制*foo{CODE}到其他地方而不是别名?或者是否有另一种方法来解决这个问题?

4

3 回答 3

3

我自己想通了。我必须使用 typeglob 的CODE一部分,而不是将整个 typeglob 分配给另一个 typeglob。这样,它似乎可以复制。

*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 回答