处理相互使用的模块的最佳方法是什么?

Axe*_*man 2 perl perl-module

处理相互使用的模块的最佳方法是什么?

假设我有一个具有哈希函数的模块:

# 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
Run Code Online (Sandbox Code Playgroud)

另一个模块已经分段列出:

# 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
Run Code Online (Sandbox Code Playgroud)

假设足够的这些实用程序函数足够方便我将在BEGIN语句中使用它们并导入函数来处理参数列表或配置数据.

我一直在将子定义放入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; 
}
Run Code Online (Sandbox Code Playgroud)

捕获两个我厌倦了打字的习语:

@{ func_I_hope_returns_a_listref() || [] }
Run Code Online (Sandbox Code Playgroud)

( $condition ? LIST : ())
Run Code Online (Sandbox Code Playgroud)

我在BEGIN块中定义的函数越多,我就越有可能使用这些成语块来表示逻辑,BEGIN块中需要砖块的可能性越大.

人们是否有标准的方法来处理这种语言 - 成语砖模型?

我一直在做Pure-Perl; XS会减轻一些吗?

Eri*_*rom 5

如果你想拥有相互依赖的模块,一个简单的方法就是使用具有完全限定名称的后期绑定子程序调用(换句话说,在子调用上使用parens).原型不会工作,但perl不会关心,Somepackage::mysub()直到你真正尝试调用它.当我编写相互依赖的模块时,我通常会将它们保存在同一个文件中,这样可以完全避免导入,从而简化了这种情况.

此外,不需要在BEGIN块中定义子,因为sub name {...}它是相同的BEGIN {*name = sub {...}}