处理相互使用的模块的最佳方式是什么?
假设我有一个模块,它有散列函数:
# Really::Useful::Functions::On::Hash.pm
use base qw<Exporter>;
use strict;
use warnings;
use Really::Useful::Functions::On::List qw<transform_list>;
our @EXPORT_OK = qw<transform_hash transform_hash_as_list ...>;
#...
sub transform_hash { ... }
#...
sub transform_hash_as_list {
return transform_list( %{ shift() } );
}
#...
1另一个模块已经被分割出来用于列表:
# Really::Useful::Functions::On::List.pm
use base qw<Exporter>;
use strict;
use warnings;
use Really::Useful::Functions::On::Hash qw<transform_hash>;
our @EXPORT_OK = qw<transform_list some_func ...>;
#...
sub transform_list { ... }
#...
sub some_func {
my %params = transform_hash @_;
#...
}
#...
1假设这些实用函数足够方便,我想在BEGIN语句和import函数中使用它们来处理参数列表或配置数据。
我一直在将子定义放入BEGIN块中,以确保无论何时有人包含模块,都可以使用它们。但是我已经进入了复杂的竞争条件,其中定义不是在BEGIN块中完成的。
我将不断发展的代码习惯用法放到模块中,这样我就可以重复使用我发现自己反复编码的任何习惯用法。例如:
sub list_if {
my $condition = shift;
return unless $condition;
my $more_args = scalar @_;
my $arg_list = @_ > 1 ? \@_ : @_ ? shift : $condition;
if (( reftype( $arg_list ) || '' ) eq 'ARRAY' ) {
return wantarray ? @$arg_list : $arg_list;
}
elsif ( $more_args ) {
return $arg_list;
}
return;
}捕获了两个我有点厌倦打字的习惯用法:
@{ func_I_hope_returns_a_listref() || [] }和
( $condition ? LIST : ())我在BEGIN块中定义的函数越多,我就越有可能使用这些惯用的bricks来表达逻辑,BEGIN块中越有可能需要bricks。
人们有标准的方法来处理这种语言习语砖块模型吗?
我主要是在做纯Perl;XS会减轻一些这个问题吗?
发布于 2010-06-17 00:50:37
如果您希望拥有相互依赖的模块,一种简单的方法是使用具有完全限定名的后期绑定子例程调用(换句话说,在子调用中使用括号)。原型不起作用,但是直到您实际尝试调用Somepackage::mysub()时,perl才会关心它是否被定义。当我编写相互依赖的模块时,我通常将它们保存在同一个文件中,这样可以完全避免导入,从而简化了这种情况。
此外,由于sub name {...}与BEGIN {*name = sub {...}}相同,因此不需要在BEGIN块中定义sub
发布于 2010-06-16 23:37:09
如果两个模块是相互依赖的,那么设计就有问题。如果我是你,我会考虑重构我的模块。
发布于 2010-06-17 00:20:01
你可以有两个相互调用的模块,因为这些调用是在运行时完成的,到那时“一切”都已经加载好了。然而,(显然)这意味着你需要在不爆炸的情况下进入运行时阶段。一种常见的方法是让早于这两个模块中任何一个的其他模块对这两个模块都执行use。作为删除直接use语句的直接结果,您将丢失这些导入,但是将符号从一个模块导入到另一个模块无论如何都不是一个好主意。
看看你写的代码,我很惊讶你想出了这么多处理数据的“新”方法,以至于你觉得有必要把它们放到单独的库中。您看过标准库Hash::Util、List::Util和List::MoreUtils吗?我建议您后退一步,使用标准库,以一种更地道的Perlish方式编写代码。
https://stackoverflow.com/questions/3054780
复制相似问题