2014-02-12 5 views
5

Ich möchte Elemente aus einer Liste abrufen, die in einer Moose-Klasse gespeichert ist. Die Klasse kann diese Liste selbst füllen. Es ist ein bisschen wie ein Iterator, außer dass ich den Iterator zurücksetzen und damit beginnen kann, die gleichen Elemente aus dieser Liste zu holen, als hätte ich es noch nicht getan. Ich beabsichtige, rufen Sie wie folgt vor:Ist Moose verpflichtet, Builder nach Aufruf zu Clearer wieder aufzurufen?

while(my $slotlist = $class->get_next_slotlist) { 
    # do something with $slotlist 
} 

Abgesehen davon, dass, wie gesagt, ich will die gleichen Elemente wieder zu einem späteren Zeitpunkt wiederholen über:

$class->reset_slotlists; 
while(my $slotlist = $class->get_next_slotlist) { 
    # do something with $slotlist 
} 

Ich dachte an die Klasse an der Gestaltung die Linien der folgenden abgespeckte (mock) Version:

package List; 
use Moose; 

has '_data' => (
    traits => [ 'Array' ], 
    is  => 'ro', 
    predicate => 'has_data', 
    lazy  => 1, 
    builder => '_build_data', 
    clearer => 'reset', 
    handles => { 
     next => 'shift', 
    }, 
); 

sub _build_data { [ 'abc', 'def' ] } 

package main; 
use strict; 
use warnings; 
use Test::More; 
use Test::Pretty; 

my $list = List->new; 
ok ! $list->has_data; 
is $list->next, 'abc'; 
is $list->next, 'def'; 
is $list->next, undef; 
is $list->next, undef; 
$list->reset; 
is $list->next, 'abc', 'Moose calls builder again after clearing'; 
is $list->next, 'def'; 
is $list->next, undef; 
is $list->next, undef; 
ok $list->has_data; 

done_testing; 

Als ich dies ausführen, Moose die Erbauer wieder rufen, nachdem der Anruf() zurückgesetzt werden (dh, desto klarer). Meine Frage ist jetzt: Ist dieses Verhalten garantiert? Die Dokumentation sagt nicht.

(Während ich diese Frage eintippte, fragte ich mich auch: Denkst du, das ist schlechtes Design? Ich mag die Iterator-ähnliche Schnittstelle, sehr elegant auf der Anrufseite und einfach zu implementieren. Aber ist diese Frage ein Zeichen dass das Design nicht gut ist?)

+0

Sie sollten wahrscheinlich, dass in #moose auf irc.perl.org äußern. Die Verantwortlichen für Elch werden es am besten wissen. – simbabque

Antwort

7

Ja, wenn ein Lazy-Attribut gelöscht wurde, wird der Wert beim nächsten Aufruf eines Accessors erneut erstellt.

Löschen _data ist im Wesentlichen wie tun delete($self->{_data}). Oder es wäre, wenn Moose-Objekte Hashrezepte wären, aber keine Hashrezepte, sondern Objekte. (Tatsächlich sind sie Hashrefs darunter, aber ein Teil der Elch-Erfahrung ist, dass wir vorgeben sollen, dass wir das nicht wissen. Gesicht zwinkern.)

Lazy Attribute verwenden, um zu entscheiden, ob der Wert erstellt werden muss .

Ich glaube nicht, es ist ein schlechtes Design, aber wenn das Array groß ist, dann eine Kopie in _data hält iterativ zu zerstören mit shift ist möglicherweise Speicher zu verschwenden. Sie können einfach einen Zähler von dem, wo Sie in dem Array sind, behalten und es jedes Mal erhöhen.

Update: Sie haben Recht, dass dies nicht sehr gut dokumentiert ist.

Verwandte Themen