2010-07-08 7 views
6

mi sto trovando me stesso più volte a scrivere e riscrivere il seguente tipo di codice:Esiste un modulo Perl per configurare un oggetto da una configurazione predefinita più un hashref di configurazioni opzionali?

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

Prima di fare il mio modulo per fare questo, mi stavo chiedendo se c'è qualcosa già su CPAN come quello? Voglio solo questa funzionalità sopra molto semplice, quindi suggerire di usare Moose non è una risposta adatta a questa domanda.

risposta

4

Params::Validate potrebbe essere di qualche aiuto. Ti consentirebbe di eliminare l'hash %defaults e specificare i valori predefiniti per ogni parametro (possibilmente facoltativo).

Inoltre, è possibile renderlo un po 'meno dettagliato utilizzando map. Naturalmente, questo ignorerà silenziosamente argomenti non validi.

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

uscita:

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

OK Accetto che non c'è una risposta in tal senso, quindi accetta per aver menzionato Params :: Validate, che potrebbe essere la cosa più vicina a ciò che ho chiesto. –

+0

;-) - Grazie. –

11

Moose supporta i valori predefiniti per gli attributi, ad esempio:

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

Ma se non si vuole imboccare la strada Moose, un modo più semplice di ottenere ciò che si vuole è:

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

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

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

    # error checking here 

    return bless $self, $package; 
} 

Dal momento che la specificazione della stessa chiave hash due volte in un'inizializzazione dell'hash limiterà il primo, qualsiasi chiave in %config semplicemente sovrascriverà quelle in %defaults.

+1

Grazie per la punta con l'hash raddoppiato. Ho sicuramente bisogno di verificare la presenza di materiale vagante in% config. –

+1

Il trucco dell'hash raddoppiato sembra molto bello e sembra funzionare per me, ma con mia sorpresa perldata in realtà non dico cosa succede quando ad un hash viene assegnato un elenco contenente chiavi duplicate. Hai qualche documentazione per questo? –

+3

@random, c'è una breve menzione in 'perlfaq4', vedi" Come posso ottenere le chiavi univoche da due hash? " a http://perldoc.perl.org/perlfaq4.html#How-can-I-get-the-unique-keys-from-two-hashes? – friedo

3

Se stai già utilizzando Moose nei tuoi moduli, puoi ottenere questo comportamento combinando MooseX::Getopt e MooseX::SimpleConfig. Il file di configurazione può contenere le impostazioni di default, e poi si ignora nulla, se necessario passando quei valori al costruttore:

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', 
); 
Problemi correlati