2

我有一些导出各种功能的 Perl 模块。(我们已经有几年没有在新模块中使用 @EXPORT 了,但保留它是为了与旧脚本兼容。)

我已经重命名了许多函数和方法以更改为一致的命名策略,并认为然后添加一个行列表,例如

*directory_error      = *directoryError;

在模块的末尾只会将旧名称别名为新名称。

这有效,除非导出旧名称,并且调用脚本以非限定名称调用函数:在这种情况下,它报告未找到子例程(在调用模块中)。

我猜发生的事情是,当别名尚未创建时,Exporter 会在 BEGIN 中准备列表;但我尝试将 typeglob 赋值放在 BEGIN 块中,但没有帮助。

我已经尝试过 AUTOLOAD,但当然这不会使该名称在调用上下文中可用。当然,我可以编写一系列包装函数,但这很乏味。我可能会自动生成包装函数,但我不确定如何。

任何关于处理此问题的简洁方法的建议?

4

3 回答 3

2

出口

手动调用 @EXPORT =() 东西变得有点憔悴。

package Bar;
use strict;
use warnings;

use Sub::Exporter -setup => {
    exports => [qw[ foo ]],
    groups  => {
        default => [qw[ foo ]],
    }
};

sub foo(){

};


1;

利用:

use strict;
use warnings;
use Bar  foo => { -as-> 'Foo' }; 

Sub::Exporter 可以做很多很棒的事情,比如组导出、组排除、构建器方法(即:它导出的 subs 的工作方式由传递的参数决定,subs 是在其他 subs 中生成的,等等)

重命名

对于重命名事物,最好有一个辅助函数,它只是作为一个遗留函数,当 Carp() 被调用时,它会推荐指向它的代码,以将其移动到新方法。这将提高代码范围内的一致性。

然后,当您的测试停止发出警告时,您可以删除旧功能。

sub old {  # line 1
   Carp::carp('Legacy function \'old\' called, please move to \'newmethod\' '); 
   goto &newmethod; # this passes @_ literally and hides itself from the stack trace. 
} # line 4

sub newmethod { # line 6
   Carp::cluck('In New Method'); 
   return 5;
} # line 9

print old(), "\n";  # line 11
已调用旧函数“旧”,请移至 code.pl 第 2 行的“新方法”
    main::old() 在 code.pl 第 11 行调用
在 code.pl 第 7 行的新方法中
    main::newmethod() 在 code.pl 第 11 行调用
5

请注意 newmethod 中的警告看起来与直接调用它们的方式完全相同。

于 2009-05-01T17:01:11.610 回答
1

以下对我有用。这似乎是您所描述的;你一定在某个地方犯了错误。

主脚本:

use strict;
use warnings;
use Bar;

baz();

模块:

package Bar;
use strict;
use warnings;

require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(baz);

sub Baz { print "Baz() here\n" }

*baz = *Baz;

1;
于 2009-04-29T13:21:26.880 回答
0

如果您希望两个名称都可见,则必须导出这两个名称。使用迈克尔卡曼的答案作为基础,你需要

our @EXPORT = qw(Baz baz);

或者

our @EXPORT    = qw(Baz);
our @EXPORT_OK = qw(baz);

如果您希望能够调用程序中的任何一个。仅仅因为它们指向同一个 coderef 并不意味着该 coderef 的所有名称都将在一个名称时被导出。

于 2009-04-29T14:06:51.390 回答