2010-11-19 10 views
6

Ho un sacco di funzioni pigre in un oggetto Moose.Come posso costruire tutte le caratteristiche di Moose pigro?

Alcuni costruttori richiedono del tempo per terminare.

Vorrei invocare tutti i builder (il dump l'oggetto "bomplete"). Posso creare tutte le funzionalità lazy in una volta o devo chiamare manualmente ciascuna funzione per far sì che il builder funzioni?

+1

Non dovresti usare 'default' per quello? Pensavo che il punto di "pigro" fosse di posticipare la creazione del valore dell'attributo fino al primo utilizzo. Se hai bisogno di impostare tutti gli attributi nella costruzione degli oggetti, 'default' sembra più utile. Oppure puoi fornire il tuo metodo 'BUILD'. –

+0

Questo è un idioma ragionevolmente comune e ci sono alcuni motivi decenti per questo. – hobbs

+0

Fondamentalmente, si potrebbe fare tutto il lavoro in 'BUILD', ma è meglio avere un metodo per attributo. E se hai intenzione di avere un metodo per attributo per calcolare il valore, allora potrebbe anche essere un costruttore. Ma se un costruttore sta per accedere ad altri attributi, allora l'attributo costruito deve essere pigro per essere sicuro che sia stato inizializzato. E non c'è un "pigro, ma solo un * piccolo bit * pigro" opzione attributo :) – hobbs

risposta

6

Se si desidera avere attributi "pigri" con i builder, ma assicurarsi che i loro valori siano costruiti prima dei ritorni new, la solita cosa da fare è chiamare gli accessori in BUILD.

sub BUILD { 
    my ($self) = @_; 

    $self->foo; 
    $self->bar; 
} 

è sufficiente per ottenere il lavoro fatto, ma probabilmente è meglio aggiungere un commento e spiegare questo codice apparentemente inutile a qualcuno che non conosce l'idioma.

3

Forse potresti usare la meta classe per ottenere l'elenco degli attributi "pigri". Per esempio:

package Test; 

use Moose; 


has ['attr1', 'attr2'] => (is => 'rw', lazy_build => 1); 
has ['attr3', 'attr4'] => (is => 'rw',); 

sub BUILD { 
    my $self = shift; 


    my $meta = $self->meta; 

     foreach my $attribute_name (sort $meta->get_attribute_list) { 

     my $attribute = $meta->get_attribute($attribute_name); 

     if ($attribute->has_builder) { 
      my $code = $self->can($attribute_name); 
      $self->$code; 

     } 
    } 

} 


    sub _build_attr1 { 1 } 
    sub _build_attr2 { 1 } 
2

Ho avuto questo requisito esatto diverse volte in passato, e oggi ho dovuto farlo dal metaclasse, il che significava non tweaking BUILD permesso. Comunque ho pensato che sarebbe stato bello condividere dato che fondamentalmente fa esattamente quello etere menzionati:

'Permetterebbe marcatura attributi "questo è pigro, perché dipende su altri valori degli attributi da costruire, ma voglio . di essere pungolato prima finiture di costruzione "'

Tuttavia, derp derp mi hanno alcuna idea di come fare un modulo CPAN quindi ecco alcuni codici: https://gist.github.com/TiMBuS/5787018

Mettere il sopra in Late.pm e allora puoi usare i Mi piace così:

package Thing; 
use Moose; 
use Late; 

has 'foo' => (
    is  => 'ro', 
    default => sub {print "setting foo to 10\n"; 10}, 
); 

has 'bar' => (
    is  => 'ro', 
    default => sub {print 'late bar being set to ', $_[0]->foo*2, "\n"; $_[0]->foo*2}, 
    late => 1, 
); 

#If you want.. 
__PACKAGE__->meta->make_immutable; 
1; 


package main; 

Thing->new(); 
#`bar` will be initialized to 20 right now, and always after `foo`. 
#You can even set `foo` to 'lazy' or 'late' and it will still work. 
Problemi correlati