我刚才开始说我对创建Perl模块没有任何经验,所以如果我离开这里我很抱歉。
假设我正在创建一些模块:
foo::bar
foo::bar::a
foo::bar::b
由于我不知道它们叫什么,我称之为a.pm和b.pm模块“子模块”,因为它们与bar.pm模块有关,但仍然可能有点独立。
所以我的一个Perl脚本可以使用foo :: bar :: a,另一个脚本可以使用foo :: bar :: b,也许我有另一个脚本需要使用“a”和“b”中的函数”。而不是这样说:
use foo::bar;
use foo::bar::a qw(one two);
use foo::bar::b;
我想做这样的事情:
use foo::bar qw(:a :b);
在我看来,这会让我的脚本可以访问bar.pm,a.pm和b.pm中的所有内容。
我测试了这样的东西,我显然是错的。
这样的事情可能吗?我想我可以使用bar.pm使用a.pm和b.pm,然后使用“包装”函数将调用传递给“子模块”,但似乎会有更简单的方法。
答案 0 :(得分:5)
查看我的Test::Data模块,了解有关这样做的示例。即使你能实现它,我也从未如此喜欢这个结果。您可能想要考虑插件或Mixin方法。 CPAN上有一些模块可以帮助解决这个问题。
这是我为Test :: Data编写的自定义import
:
sub import { my $self = shift; my $caller = caller; foreach my $package ( @_ ) { my $full_package = "Test::Data::$package"; eval "require $full_package; 1"; if( $@ ) { carp "Could not require Test::Data::$package: $@"; } $full_package->export($caller); } }
答案 1 :(得分:2)
是的,你可以这样做。它可能涉及在foo :: bar中编写一个自定义的“子导入”,它以你想要的方式解释传入的参数。
可能你现在正在使用Exporter,而且它缺乏对你的语法的支持。您会发现Exporter实现的模块语法没有什么特别之处;这只是一个共同的惯例。但是,您可能希望了解如何开展业务以深入了解您的需求。
答案 2 :(得分:1)
如果您不知道模块的名称,为什么要包含它?你不应该包含它。只在(调用)模块中包含一个需要它的模块,而不是其他任何模块。
即:如果您正在使用它,那么“使用”它。如果您不使用它,请不要“使用”它。
答案 3 :(得分:0)
另请尝试查看Class::MixinFactory
答案 4 :(得分:0)
是的,但您必须装备自己的导入子:
use strict;
use warnings;
package ab;
use base qw<Exporter>;
our @EXPORT_OK;
our %EXPORT_TAGS;
BEGIN {
@EXPORT_OK = qw<>;
%EXPORT_TAGS = ( a => 1, b => 1, all => \@EXPORT_OK );
}
sub setup_part {
#use Smart::Comments;
my $code = shift;
my $mini_path = "foo/bar/$code.pm";
return if exists $INC{$mini_path};
require $mini_path;
my $arr_ref
= do { no strict 'refs';
\@{Symbol::qualify( 'EXPORT_OK', $code )};
};
$code->import( @$arr_ref );
push @EXPORT_OK, @$arr_ref;
$EXPORT_TAGS{$code} = [ @$arr_ref ];
return;
}
sub import {
my ( $package_name, @imports ) = @_;
my %import_hash = map { $_ => 1 } @imports;
if ( exists $import_hash{':all'} ) {
@import_hash{qw<:a :b>} = ( 1, 1 );
}
foreach my $import ( grep { exists $import_hash{$_} } qw<:a :b> ) {
setup_part( substr( $import, 1 ));
}
goto &{Exporter->can( 'import' )};
}
1;
答案 5 :(得分:0)
我已经找到了类似于最近的解决方案。我知道 - 太老了,但我想通过 brian d foy 评论答案( 2月12日&09; 09,15:55 )但是遗憾的是,我没有足够的声誉来实现这一目标。这就是我将评论添加为新回复的原因。
他的回答帮助我解决了类似于最近的问题。但如果与use lib
一起使用,则需要进行一些修改。
我有一堆看起来像A::B::*
的模块。那些应该由通用模块A::B
加载到脚本中。所有这些模块都在其文件中,与加载脚本位于同一目录下。使用 brian d foy 建议的机制,我们可以获得许多子例程重新定义的错误。我相信,为了避免所有这些,我找到了更好的解决方案,优于no warnings 'redefine'
。现在,我们可以在主脚本中自由使用use lib
,no warnings 'redefine'
或shift @INC, ...
。
sub import { @TAGS = ( @_ ); my $me = shift @TAGS; ( my $pm = $me ) =~ s|::|/|g; $pm .= ".pm"; ( $dir = $INC{$pm} ) =~ s/\.pm$//; foreach ( glob "$dir/*.pm" ) { /(\w+)\.pm$/; my $module = "${me}::$1"; eval "use $module qw(:all)"; # You are free to use any items in the exporting list die "$me: Error while loading $module from $_: $@\n" if $@; } # Fill in @EXPORT_OK and %EXPORT_TAGS manually from each A::B::*::EXPORT_OK # ... goto &{ Exporter->can( "import" ) }; }