以下是我所拥有的重要内容:
sub logger {
my $self = shift;
my %def = (
type => $self->{options}{name},
severity => 1,
date => $self->now(),
message => ''
);
my %opt = %def;
if ( my $ref = shift ) {
%opt = (%def, %{$ref});
}
croak('message is a required option') if $opt{message} eq '';
warn($opt{type} . ': ' . $opt{message} . "\n") if ( $self->{_verbose} );
# Do some other interesting things.
}
那么我可以这样称呼它:
$op->logger({message => 'Some message'});
因此,如果我的任何参数丢失,它们将获得我在%def hash中指定的默认值。如果缺少必需的参数,我就死了。
它的基础是我使用用户指定的内容重载def散列。
if ( my $ref = shift ) {
%opt = (%def, %{$ref});
}
问题是他们可以在我的选项列表之外指定内容,或者发送散列而不是散列引用,标量或undef,或许多其他可能爆炸的方式。
我确信有更优雅的方法可以解决这个问题 我好像回想起一些使用ref()的代码,如果没有传入任何代码,它就不会爆炸。
答案 0 :(得分:2)
Method::Signatures正是您正在寻找的,而且非常优雅:
method logger (
:$type = $self->{options}{name},
:$severity = 1,
:$date = $self->now,
:$message! # No default and required, so croaks if not provided by caller.
) {
my %opt = (
type => $type,
severity => $severity,
date => $date,
message => $message
);
# Do some other interesting things.
}
签名中的冒号指定名为参数(作为哈希传递)。 <{1}}后面的感叹号使其成为必需。
答案 1 :(得分:0)
如果穆斯对你来说太沉重,那么处理这个的优雅方式就是在穆斯,或者甚至是鼠标或者Moo中都很方便的捆绑。
答案 2 :(得分:0)
我想我会做那样的事情。毫无疑问,虽然有很多CPAN模块可以使这更简单。
sub logger {
my $self = shift;
# Set $ref to an empty hash ref if it's not given.
# This makes a lot of later code far simpler
my $ref = shift || {};
# Check you have a hash ref
unless (ref $ref eq 'HASH') {
die "Argument to logger must be a hash ref";
}
my %def = (
type => $self->{options}{name},
severity => 1,
date => $self->now(),
message => '',
);
my %opt = (%def, %$ref);
# Now check we only have valid options. Assume that all valid
# keys are in %def
foreach (keys %opt) {
delete $opt{$_} unless exists $def{$_};
}
croak('message is a required option') if $opt{message} eq '';
warn($opt{type} . ': ' . $opt{message} . "\n") if ( $self->{_verbose} );
# Do some other interesting things.
}