What's the best way to handle modules that use each other?
Let's say I have a module which has functions for hashes:
# 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
And another module has been segmented out for lists:
# 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
Suppose that enough of these utility functions are handy enough that I'll want to use them in BEGIN statements and import functions to process parameter lists or configuration data.
I have been putting sub definitions into BEGIN blocks to make sure they are ready to use whenever somebody includes the module. But I have gotten into hairy race conditions where a definition is not completed in a BEGIN block.
I put evolving code idioms into modules so that I can reuse any idiom I find myself coding over and over again. For instance:
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;
}
captures two idioms that I'm kind of tired of typing:
@{ func_I_hope_returns_a_listref() || [] }
and
( $condition ? LIST : ())
The more I define functions in BEGIN blocks, the more likely I'll use these idiom bricks to express the logic the more likely that bricks are needed in BEGIN blocks.
Do people have standard ways of dealing with this sort of language-idiom-brick model?
I've been doing mostly Pure-Perl; will XS alleviate some of this?