假设我有一个像这样的“make_members”方法。
sub make_members {
my ($number_members) = @_;
my $rows = SomeDBIModule->select();
my $count = @$rows;
for ( my $i = $count + 1; $i < $count + 1 + $number_members; $i++ ) {
$rows->insert(
name => "name".$i,
type => "A",
created_at => time,
);
}
}
到目前为止一切顺利。现在想象一下该方法可以作为输入,用户数量类型a,类型b和类型c所需的:
sub make_members {
my ($number_members, $n_members_type_a, $n_members_type_b, $n_members_type_c) = @_;
#....
写下这首先想到的是制作3个循环。第一个
for ( my $i = $count + 1; $i < $count + 1 + $n_members_type_a; $i++ ){
$rows->insert(
name => "name".$i,
type => "A",
#....
$ count + 1和$ n_members_type_b之间的第二个。 $ count + 1和$ n_members_type_c之间的第三个。
这看起来太长而且糟糕。 有没有更好的写作方式?
答案 0 :(得分:2)
“三个或更多,请使用for
”。
将其打包到另一个循环中
sub make_members {
my %number_members_for_type;
@number_members_for_type{qw/A B C/} = @_;
my $rows = ...;
while (my ($type, $num) = each %number_members_for_type) {
for my $i ( @$rows + 1 .. @$rows + $num ) {
$rows->insert(
name => "name$i",
type => $type,
...
)
}
}
}
这假定它被称为make_members($n_type_a, $n_type_b, $n_type_c)
。
使用参数的哈希可以很好地扩展。
如果将哈希作为参数传递,我们可以概括这一点。如果name
属性必须是唯一ID,和插入只能由此函数完成,那么我们也可以优雅地管理它:
sub make_inserter {
my ($rows) = @_;
my $id_counter = @$rows;
return sub {
my %type2nums = @_;
while (my ($type, $num) = each %type2nums) {
for my $i ($id_counter + 1 .. $id_counter + $num) {
$rows->insert(
name => "name$i",
type => $type,
...
);
}
$id_counter += $num;
}
};
}
...
# Careful! Do not make an inserter for the same handle twice!
my $make_members = make_inserter(SomeDBIModule->select);
$make_members->(A => 2, B => 3);
如果键的顺序很重要,我们应该这样做,因为哈希键的顺序是未定义的:
... # as before
return sub {
while (my ($type, $num) = splice @_, 0, 2) {
... # as before
}
};
答案 1 :(得分:0)
对方法重复许多类似的参数通常表明可以进行一些简化。
因此,不要取一个数字列表,而是将类型作为参数接受:
sub make_members {
my ($number_members, $member_type) = @_;
以后:
$rows->insert(
name => "name".$i,
type => $member_type,
created_at => time,
);
然后适当地调用代码。例如,创建x倍“A”,y乘以“B”,z乘以“C”:
%numbers_of = ( "A" => 4, "B" => 5, "C" => 2 );
for my $type (keys %numbers_of) {
make_members( $numbers_of{ $type }, $type );
}