如何在Perl中重命名导出的函数?

如何在Perl中重命名导出的函数?,perl,exporter,typeglob,Perl,Exporter,Typeglob,我有一些导出各种函数的Perl模块。(我们已经有几年没有在新模块中使用@EXPORT了,但为了与旧脚本兼容,我们保留了它。) 我已经重命名了许多函数和方法,以更改为一致的命名策略,并认为可以添加一系列行,如 *directory_error = *directoryError; 在模块的末尾,只需将旧名称别名为新名称 除非导出旧名称,并且调用脚本使用非限定名称调用函数:在这种情况下,它报告未找到子例程(在调用模块中) 我猜现在发生的事情是Exporter在一个BEGIN中准备列表,而

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

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

*directory_error      = *directoryError;
在模块的末尾,只需将旧名称别名为新名称

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

我猜现在发生的事情是Exporter在一个BEGIN中准备列表,而别名还没有创建;但是我试着把typeglob赋值放在BEGIN块中,但没有用

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


有什么好的处理方法的建议吗?

以下内容对我很有用。这似乎就是你所描述的;你一定是在什么地方出错了

主脚本:

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;

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

our @EXPORT = qw(Baz baz);

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

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

package Bar;
use strict;
use warnings;

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

sub foo(){

};


1;
使用:

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

更名 对于重命名对象,最好使用一个二级函数,该函数在调用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
调用了旧函数'old',请移到code.pl第2行的'newmethod' main::old()在code.pl第11行调用 在code.pl第7行的新方法中 main::newmethod()在code.pl第11行调用 5. 注意newmethod中的警告看起来与直接调用的警告完全一样


你说得对!它仍然不起作用(事实上,在您的示例中,它说的是“Undefined subroutine Bar::baz”),但它一定是其他东西。谢谢你的帮助。事实上,这是因为在同一个文件中有第二个包(另一件事我们不再做了),而别名(*baz=*baz)在错误的包中!记下另一个不将多个模块放在同一个文件中的原因。你想说的是“使baz成为一个子程序”,但是*baz=*baz说的是“使$baz、@baz、%baz等等。未定义,&baz成为一个子程序。”*baz=\&baz会更简洁,不太可能引起问题。比较:$perl-le'subfoo{42}$巴=10*bar=\&foo;打印条();打印$bar'和:perl-le'sub foo{42}$巴=10*bar=*foo;打印条();打印$bar'如果我正确阅读了原始帖子@EXPORT(即无条件导出)仅用于向后兼容。据推测,依赖于此的用户只使用旧名称。我猜使用新名称的模块通过@EXPORT\u OK或%EXPORT\u标记显式导入它们。
use strict;
use warnings;
use Bar  foo => { -as-> 'Foo' }; 
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
Legacy function 'old' called, please move to 'newmethod' at code.pl line 2 main::old() called at code.pl line 11 In New Method at code.pl line 7 main::newmethod() called at code.pl line 11 5