2016-08-03 24 views
6

Was ist der beste Weg, Attribute träge zu bauen?Wie schreibt man faule Accessoren

class I { 
    has $!cheezeburger; 

    method cheezeburger { 
     given $!cheezeburger { 
      when .so {return $_} 
      default { 
       # build $cheezeburger, set attribute to it, return 
      } 
     } 
    } 
} 

Das ist eine Menge Cheezeburger. Was könnte eine weniger wortreiche Art sein?

+4

'methode cheezeburger {$! Cheezeburger // = ...}' –

Antwort

2

Die pragmatische Lösung von Brad gegeben, die das Attribut initialisiert, wenn es nicht definiert ist, sollte genug für viele Fälle gut sein:

class Foo { 
    has $!cheezeburger; 
    method cheezeburger { 
     $!cheezeburger //= do { ... } 
    } 
} 

Ein anderer Ansatz wäre does werden unter Verwendung der Zugriffsmethode zu ersetzen, indem in einer Rolle Mischen während sein erster Anruf, schwarze Magie (aka NQP ops) das private Attribut zuzugreifen:

class Foo { 
    has $!cheezeburger; 
    method cheezeburger { 
     self does role { 
      method cheezeburger { 
       use nqp; 
       nqp::getattr(self, Foo, '$!cheezeburger'); 
      } 
     } 
     $!cheezeburger = do { ... } 
    } 
} 
+0

Ich mag den 'do'-Block mit definiert-oder-gleich – beasy

4
class A { 
    has $!lazy; 
    method BUILD { $!lazy := Nil }; 
    method lazy { $!lazy := (my $a = 42) if $!lazy =:= Nil; $!lazy } 
}; 
my $a = A.new; 
say [$a.lazy, $a.lazy]; 

Wenn $!lazy soll nicht definiert Werte, die Sie durch ein paar Schleifen hüpfen müssen halten. Zuerst binden wir Nil an $!lazy, um einen Wert zu halten, den ein Container nicht halten kann. Wenn $!lazy immer noch an Nil gebunden ist, erstellen wir einen neuen Container und weisen ihm einen Wert zu. Wenn der Wert unveränderbar ist, benötigen Sie den zusätzlichen Container nicht. Alle Typeinschränkungen, die Sie für $! Lazy benötigen, müssen auf $a stehen, da Constraints eine Eigenschaft eines Containers sind, nicht die Variable/class-property.

+0

: \ immer noch daran arbeiten, dies zu erfassen. thx für das Material – beasy

+2

Variablen können an Container gebunden werden (über den Zuweisungsoperator '=') und an unveränderbare Werte (über den Bindeoperator ': ='). Um zu verstehen, welche Container https://docs.perl6.org/language/containers#Custom_containers sehen. –

4

Bestehende Module

Es gibt zwei lazy attribute modules.

Ordinary Code

Brads $!cheezeburger //= do { ... }; scheint wie eine ziemlich straight-forward-Lösung, die für viele Anwendungsfälle ausreichen würde.

Etwas besser?

Sie können feststellen, dass # perl6 Folk wollen oder etwas besseres bieten kann.

Die letzten ernsthaften # perl6 Diskussionen, über die ich im Zusammenhang mit fauler Attributinitialisierung Bescheid weiß, fanden 2015 am 5., 7., 20. und 5., 8. und 20. Mai statt. Suche nach "wird faul" in pages of #perl6 log with at least one "will lazy" match. Diese Diskussionen haben gezeigt, dass rjbs, mst und andere Moose-Benutzer für eine schöne faule Attributinitialisierung verwendet wurden und eine Lösung zu Rakudo hinzugefügt wurde. Es wurde dann rückgängig gemacht, weil masak und andere dachten, dass es Probleme gäbe und sie dachten, dass schöne Lösungen im Modulraum erstellt und dann in den Kern zurückversetzt werden könnten, wenn das sinnvoll erschien.