开发者

Simplified default parameters handling within a perl OO package

开发者 https://www.devze.com 2023-04-10 06:26 出处:网络
Here is the important subset of what I have: sub logger { my $self = shift; my %def =( type => $self->{options}{name},

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.
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号