Там какой-либо модуль Perl должен настроить объект из конфигурации по умолчанию плюс hashref дополнительных конфигураций?

Я пишу неоднократно и переписать следующий вид кода:

 my %default = (x => "a", y => "b");
 sub new
 {
      my ($package, $config) = @_;
      my $self = {%default};
      for my $k (keys %default) {
           $self->{$k} = $config->{$k} if defined $config->{$k};
      }
      for my $k (keys %$config) {
           if (! exists $default{$k}) {
                carp "Unknown config option $k\n";
           }
      }
      bless $self;
      # etc. etc.
 }

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

6
задан 8 July 2010 в 02:47
поделиться

3 ответа

Params::Validate может оказать некоторую помощь. Это позволит вам отказаться от хэша %defaults и указать значения по умолчанию для каждого (возможно, необязательного) параметра.

Кроме того, вы можете сделать это немного менее подробным, используя map. Конечно, это будет молча игнорировать недопустимые аргументы.

#!/usr/bin/perl

package My::Class;

use strict; use warnings;

my %defaults = ( x => 'a', y => 'b' );

sub new {
    my $class = shift;
    my ($args) = @_;

    my $self = {
        %defaults,
        map {
            exists $args->{$_} ? ($_ => $args->{$_}) : ()
        } keys %defaults,
    };

    return bless $self, $class;
}

package main;

use strict; use warnings;

my $x = My::Class->new({ x => 1, z => 10});

use YAML;
print Dump $x;

Выход:

--- !!perl/hash:My::Class
x: 1
y: b
4
ответ дан 8 December 2019 в 12:57
поделиться

Moose поддерживает значения по умолчанию для атрибутов, например:

has 'foo' => ( is => 'rw', isa => 'Int', default => 42 );

Но если вы не хотите идти по пути Moose, более простой способ достижения того, что вы хотите:

sub new { 
    my ( $package, %config ) = @_;

    my %defaults = ( x => 'a', y => 'b' );

    my $self = { %defaults, %config };

    # error checking here

    return bless $self, $package;
}

Поскольку указание одного и того же хэш-ключа дважды в хэш-инициализации приведет к забитию первого, любые ключи в %config просто переопределяют ключи в %defaults.

11
ответ дан 8 December 2019 в 12:57
поделиться

Если вы уже используете Moose в своих модулях, вы можете получить это поведение, объединив MooseX::Getopt и MooseX::SimpleConfig. Ваш конфигурационный файл может содержать значения по умолчанию, а затем вы переопределяете все, что необходимо, передавая эти значения конструктору:

my $obj = Class->new_with_options(configfile => "myconfig.yaml", key1 => 'val', key2 => 'val');

package Class;
use Moose;
with 'MooseX::Getopt::Strict',
    'MooseX::SimpleConfig';

has configfile => (
    is => 'ro', isa => 'Str',
    traits => ['Getopt'],
    documentation => 'File containing default configs',
    lazy => 1,
    default => sub { File::Spec->catfile($base_dir, 'my_default_config.yaml') },
);

has [ qw(key1 key2) ] => (
    is => 'ro', isa => 'Str',
);
3
ответ дан 8 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: