【问题标题】:Is there any Perl module to set up an object from a default configuration plus a hashref of optional configurations?是否有任何 Perl 模块可以从默认配置和可选配置的 hashref 设置对象?
【发布时间】:2011-03-13 02:42:58
【问题描述】:

我发现自己反复编写和重写以下类型的代码:

 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 上是否已经有类似的东西?我只想要上面这个非常简单的功能,所以建议使用 Moose 不是这个问题的合适答案。

【问题讨论】:

    标签: perl cpan


    【解决方案1】:

    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 中的那些。

    【讨论】:

    • 感谢您提供双倍哈希的提示。不过,我肯定也需要检查 %config 中的杂散内容。
    • 双重哈希技巧看起来非常好,似乎对我有用,但令我惊讶的是,perldata 实际上并没有说明当哈希被分配一个包含重复键的列表时会发生什么。你有任何文件吗?
    • @random,在perlfaq4 中有一个简短的提及,请参阅“如何从两个哈希中获取唯一键?” perldoc.perl.org/…?
    • 谢谢。 Perldata 应该说明这是如何处理的,如果我能弄清楚谁维护文档,我会给他们一个补丁。
    【解决方案2】:

    如果您已经在模块中使用 Moose,您可以通过组合 MooseX::GetoptMooseX::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】:

      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

      【讨论】:

      • 好的,我接受没有真正的答案,所以接受提及 Params::Validate,这可能是我所问的最接近的事情。
      猜你喜欢
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 2019-08-24
      • 2014-10-15
      • 1970-01-01
      • 2022-09-23
      相关资源
      最近更新 更多