2010-12-07 4 views
5

Ich finde, dass eine der interessantesten Eigenschaften von Haskell und Perl6 die Möglichkeit ist, Rechenwerte aufzuschieben, bis sie tatsächlich benötigt werden.Beispiele für faule Auswertungstechniken in Perl 5?

Perl5 auf der anderen Seite mag alles sofort zu tun, aber von dem, was ich sagen kann, enthält alle notwendigen Primitiven für die faule Bewertung. Das sind:

  • einen Verweis auf @_ in einem Unterprogramm erstellt ein Array Referenz genommen wird, die den Bezeichner in der Argumentliste aliased ist, auch wenn einige dieser Kennungen noch keine Werte enthalten.
  • überladene/gebundene Objekte von solchen Unterprogrammen zurückgeben, die intern \@_ enthalten, und dann bei Bedarf deneferenzieren. (Und es gibt verschiedene CPAN-Module, die abstrahieren die tie/Überlastung Details)

Ich habe mit verschiedenen faulen Programmiertechniken in Perl zu experimentieren (Ich habe ein Modul in den Werken, die ein gutes Stück von der Haskell implementiert Prelude in Perl5 (Dinge wie Co-Rekursion: zur Definition der Fibonacci-Sequenz funktionieren bereits)). Aber ich habe das Gefühl, dass sich im Code versteckte Fehler verbergen, die sich zeigen können, wenn die Funktionen in größeren Ausdrücken/Programmen verwendet werden.

Also frage ich mich, ob es irgendwelche guten Beispiele (CPAN/blogs/books) gibt, von denen jemand weiß, dass sie Haskell/Perl6 wie Faulheit in Perl5 benutzen? Insbesondere würde ich gerne einen Code von signifikanter Größe durchlesen, der diese Art von Faulheit anwendet.

Ich möchte auch daran interessiert zu wissen, ob jemand in irgendwelche gotchas oder unlösbare Probleme laufen hat die Umsetzung lazy evaluation in Perl Umgebung 5.

+3

Ich nehme an, dass Sie Higher Order Perl gelesen haben. Es enthält eine Menge Material über Iteratoren, unendliche Ströme und Faulheit. –

Antwort

9

Höhere Ordnung Perl (frei verfügbar online) hat ein Kapitel namens "Infinite Streams". Vielleicht ist das ein guter Ausgangspunkt.

3

Ich denke, das größte Problem ein „Clash of Magics“ ist. Wenn du versuchst, etwas zu tun, hältst du es für schick und ein anderer Modulautor versucht etwas, von dem sie denken, dass es schick ist, und das Ergebnis ist Unbestimmtheit. Wessen Magie gewinnt?

Da man immer hinter die Magie einer anderen Variablen blicken oder sie sogar unbeabsichtigt entzaubern kann, sind Magien niemals kugelsicher.

Wenn Sie 100% Orthogonalität durch ausgiebige Falltests erreichen könnten, könnten Sie in der Lage sein, sich leichter auszuruhen ... vielleicht.

+1

Wenn es wirklich magisch wäre, würde es meine Gedanken und DWIM lesen. – Ether

+2

@Ether: Sie conflate * Dweomer * mit * DWIMMER *. :) – tchrist

6

Nun, Moose tut dies mit lazy loading of attributes:

Standard und Generator-Methoden
Attribute können Standardwerte haben, und Moose bieten zwei Möglichkeiten, um den Standard angeben.
["Standard" und "Builder" Optionen beschrieben ...]

Laziness
Moose können Sie, indem sie ein Attribut „lazy“ -Attribut Bevölkerung verschieben:

has 'size' => (
    is  => 'ro', 
    lazy => 1, 
    builder => '_build_size', 
); 

Wenn „faul“ wahr ist, wird der Standard nicht erzeugt, bis der Leser Methode aufgerufen wird, anstatt zur Bauzeit des Objekts. Es gibt mehrere Gründe, Sie möglicherweise wählen, dies zu tun.

Erstens, wenn der Standardwert für dieses Attribut von einigen anderen Attributen abhängt, dann muss das Attribut "faul" sein. Während der Objekterstellung werden die Standardwerte nicht in einer vorhersagbaren Reihenfolge generiert. Sie können also nicht davon ausgehen, dass ein anderes Attribut beim Generieren eines Standards ausgefüllt wird.

Zweitens gibt es oft keinen Grund, einen Standard zu berechnen, bevor er benötigt wird. Wenn Sie ein Attribut "faul" machen, können Sie die Kosten verschieben, bis das Attribut benötigt wird. Wenn das Attribut nie benötigt wird, sparen Sie etwas CPU-Zeit.

Wir empfehlen, dass Sie jedes Attribut mit einem Builder oder nicht-trivialen Standard "faul" als selbstverständlich machen.

Verwandte Themen