Simplified default parameters handling within a perl OO package
Here is the important subset of what I have:
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.
}
So then I can call it like so:
$op->logger({message => 'Some message'});
So if any of my parameters are missing, they get the defaults I've specified in the %def hash. If a required parameter is missing, I die.
The basis of it is I overload the def hash with what the user specified with this.
if ( my $ref = shift ) {
%opt = (%def, %{$ref});
}
Problem with this is they could specify things outside my list of options, or send in a hash instead of a hash ref, or a scalar, or undef, or many other ways this could blow up.
I'm sure there is a more elegant way to handle this.
I seem to recall some code using ref() that didn't blow up if nothing was passed in.Method::Signatures does precisely what you're looking for and is so very elegant :
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.
}
The colons in the signature designate named parameters (passed as a hash). The exclamation mark following $message
makes it required.
The elegant way of handling this is all conveniently bundled for you in Moose, or even Mouse or Moo if Moose is too heavy for you.
I think I'd do something like that. Although there are, no doubt, plenty of CPAN modules that make this simpler.
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.
}
精彩评论