Упрощенная обработка параметров по умолчанию в пакете Perl OO - PullRequest
2 голосов
/ 04 октября 2011

Вот важное подмножество того, что у меня есть:

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.Если требуемый параметр отсутствует, я умираю.

Основой этого является то, что я перегружаю хеш def тем, что пользователь указал с этим.

    if ( my $ref = shift ) {
        %opt = (%def, %{$ref});
    }

Проблема в том, что они могут указатьвещи, не входящие в мой список опций, или отправлять хеш вместо хеш-ссылки, или скаляра, или undef, или многих других способов, которыми это может взорваться.

Я уверен, что есть более элегантный способчтобы справиться с этим.
Кажется, я вспомнил какой-то код, использующий ref (), который не взорвался, если ничего не было передано.

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

Метод :: Подписи делает именно то, что вы ищете, и очень элегантно :

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

Двоеточия в подписи обозначают именованные параметры (передаются как хеш). Восклицательный знак после $message делает его обязательным.

0 голосов
/ 04 октября 2011

Думаю, я бы сделал что-то подобное. Хотя, без сомнения, существует множество модулей 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.
}
0 голосов
/ 04 октября 2011

Элегантный способ справиться с этим удобно для вас в Moose, или даже в Mouse или Moo, если Moose слишком тяжел для вас.

...