2010-07-08 7 views
6

estoy encontrando a mí mismo escribiendo y reescribiendo el siguiente tipo de código en varias ocasiones:¿Hay algún módulo Perl para configurar un objeto desde una configuración predeterminada más un hashref de configuraciones opcionales?

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

Antes de hacer mi propio módulo para hacer esto, me estaba preguntando si hay algo que ya están en CPAN así? Solo quiero esta funcionalidad muy simple de arriba, por lo que sugerir el uso de Moose no es una respuesta adecuada para esta pregunta.

Respuesta

4

Params::Validate podría ser de alguna ayuda. Le permitirá soltar el hash %defaults y especificar los valores predeterminados para cada parámetro (posiblemente opcional).

Además, puede hacerlo un poco menos detallado usando map. Por supuesto, esto ignorará silenciosamente los argumentos inválidos.

#!/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; 

Salida:

--- !!perl/hash:My::Class 
x: 1 
y: b
+1

OK Acepto que realmente no hay una respuesta, así que acepte mencionar Params :: Validate, que puede ser lo más parecido a lo que pregunté. –

+0

;-) - Gracias. –

11

Moose es compatible con los valores predeterminados para los atributos, por ejemplo:

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

Pero si no quiere seguir el camino de los alces, una manera más sencilla de lograr lo que quiere decir:

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

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

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

    # error checking here 

    return bless $self, $package; 
} 

Como especificar la misma clave hash dos veces en una inicialización hash será la primera, cualquier clave en %config simplemente anulará aquellas en %defaults.

+1

Gracias por la punta con el hash duplicado. Sin embargo, definitivamente necesito verificar cosas extraviadas en% config. –

+1

El doble truco de hash se ve muy bien y parece funcionar para mí, pero para mi sorpresa, Perldata en realidad no dice lo que sucede cuando a un hash se le asigna una lista que contiene claves duplicadas. ¿Tienes alguna documentación para ello? –

+3

@random, hay una breve mención de esto en 'perlfaq4', consulte" ¿Cómo puedo obtener las claves únicas de dos hashes? " en http://perldoc.perl.org/perlfaq4.html#How-can-I-get-the-unique-keys-from-two-hashes? – friedo

3

Si ya está utilizando Moose en sus módulos, puede obtener este comportamiento combinando MooseX::Getopt y MooseX::SimpleConfig. Su archivo de configuración puede contener los valores por defecto, y luego se reemplaza cualquier cosa que sea necesario pasar por esos valores al constructor:

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', 
); 
Cuestiones relacionadas