Faule Bewertung

Im Programmiersprache Theorie, faule Bewertung, oder Call-by-Need,[1] ist ein Bewertungsstrategie was die Bewertung von a verzögert Ausdruck bis sein Wert benötigt wird (Nicht-strenge Bewertung) und was auch wiederholte Bewertungen vermeidet (Teilen).[2][3]

Zu den Vorteilen der faulen Bewertung gehören:

  • Die Fähigkeit zu definieren Steuerfluss (Strukturen) als Abstraktionen statt von Primitive.
  • Die Fähigkeit zu definieren potenziell unendlich Datenstrukturen. Dies ermöglicht eine einfachere Implementierung einiger Algorithmen.
  • Die Fähigkeit, teilweise definierte Datenstrukturen zu definieren, bei denen einige Elemente Fehler sind. Dies ermöglicht schnelles Prototyping.

Eine faule Bewertung wird häufig mit mit Memoisierung, wie beschrieben in Jon Bentley's Schreiben effizienter Programme.[4] Nachdem der Wert einer Funktion für diesen Parameter oder eine Reihe von Parametern berechnet wurde, wird das Ergebnis in a gespeichert Nachschlagwerk Dies wird durch die Werte dieser Parameter indiziert; Wenn die Funktion das nächste Mal aufgerufen wird, wird die Tabelle konsultiert, um festzustellen, ob das Ergebnis für diese Kombination von Parameterwerten bereits verfügbar ist. Wenn ja, wird das gespeicherte Ergebnis einfach zurückgegeben. Wenn nicht, wird die Funktion bewertet und zur Wiederverwendung in die Nachschlagtabelle ein weiterer Eintrag hinzugefügt.

Eine faule Bewertung ist schwer mit imperativen Merkmalen wie zu kombinieren, z. Ausnahmebehandlung und Input-Output, weil die Reihenfolge der Operationen unbestimmt wird.

Das Gegenteil der faulen Bewertung ist eifrige Bewertung, manchmal als strenge Bewertung bekannt. Eine eifrige Bewertung ist die Bewertungsstrategie, die in den meisten angewendet wird Programmiersprachen.

Geschichte

Eine faule Bewertung wurde eingeführt für Lambda -Kalkül von Christopher Wadsworth[5] und angestellt von der Plessey System 250 Als kritischer Teil einer Lambda-Kalkulus-Meta-Maschine, wodurch der Auflösungsaufwand für den Zugriff auf Objekte in einem fähigen Adressraum verringert wird.[6] Für Programmiersprachen wurde es unabhängig von Peter Henderson und vorgestellt James H. Morris[7] und von Daniel P. Friedman und David S. Wise.[8][9]

Anwendungen

Eine verzögerte Bewertung wird insbesondere in verwendet Funktionelle Programmierung Sprachen. Bei Verwendung einer verzögerten Bewertung wird ein Ausdruck nicht bewertet, sobald er an eine Variable gebunden ist, aber wenn der Bewerter gezwungen ist, den Wert des Ausdrucks zu erzeugen. Das heißt eine Aussage wie x = Ausdruck; (d. H. Die Zuordnung des Ergebniss eines Ausdrucks zu einer Variablen) fordert eindeutig die Bewertung des Ausdrucks und das Ergebnis in x, aber was ist eigentlich in x ist irrelevant, bis ihr Wert über einen Verweis auf einen Hinweis auf benötigt wird x In einem späteren Ausdruck, dessen Bewertung selbst aufgeschoben werden könnte, würde der schnell wachsende Baum der Abhängigkeiten letztendlich beschnitten, um ein Symbol zu erzeugen und nicht eine andere für die Außenwelt zu sehen.[10]

Kontrollstrukturen

Eine faule Bewertung ermöglicht es, Kontrollstrukturen normal zu definieren und nicht als Primitive oder Kompilierungszeittechniken. Zum Beispiel kann man definieren If-then-else und Kurzschlussbewertung Operatoren:[11][12]

iftenelse WAHR b c = b iftenelse FALSCH b c = c -- oder WAHR || b = WAHR FALSCH || b = b -- und WAHR && b = b FALSCH && b = FALSCH 

Diese haben die übliche Semantik, d. H. ifThenElse a b c bewertet (a), dann, wenn und nur wenn (a) bewertet, um true zu bewerten (b), sonst bewertet es (c). Das heißt, genau einer von (b) oder (c) wird bewertet. Ähnlich für EasilyComputed || LotsOfWork, wenn der einfache Teil gibt WAHR Der viele Arbeitsausdruck könnte vermieden werden. Schließlich bei der Bewertung SafeToTry && Expression, wenn Safetotterie ist FALSCH Es wird keinen Versuch geben, das zu bewerten Ausdruck.

Umgekehrt in einer eifrigen Sprache die obige Definition für ifThenElse a b c würde (a), (b) und (c) unabhängig vom Wert von (a) bewerten. Dies ist nicht das gewünschte Verhalten, da (b) oder (c) haben kann NebenwirkungenNehmen Sie sich lange Zeit, um Fehler zu berechnen oder Fehler zu werfen. Normalerweise ist es möglich, benutzerdefinierte faule Kontrollstrukturen in eifrigen Sprachen als Funktionen einzuführen, obwohl sie möglicherweise von der Syntax der Sprache abweichen wenn gerufen.

Arbeiten mit unendlichen Datenstrukturen

Eine verzögerte Bewertung hat den Vorteil, dass er kalkulierbare unendliche Listen ohne unendliche Schleifen oder Größenangelegenheiten erstellen kann, die die Berechnung beeinträchtigen. Die tatsächlichen Werte werden nur bei Bedarf berechnet. Zum Beispiel könnte man eine Funktion erstellen, die eine unendliche Liste erstellt (oft als a genannt Strom) von Fibonacci -Zahlen. Die Berechnung der nDie Fibonacci -Zahl wäre lediglich die Extraktion dieses Elements aus der unendlichen Liste, was die Bewertung der ersten n -Mitglieder der Liste erzwingt.[13][14]

Nehmen Sie zum Beispiel dieses triviale Programm in Haskell:

Nummerfrominfinitelist :: Int -> Int Nummerfrominfinitelist n =  Unendlichkeit !! n - 1  wo Unendlichkeit = [1..] hauptsächlich = drucken $ Nummerfrominfinitelist 4 

In der Funktion Nummerfrominfinitelist, der Wert von Unendlichkeit ist ein unendlicher Bereich, aber bis ein tatsächlicher Wert (oder genauer gesagt ein bestimmter Wert bei einem bestimmten Index) erforderlich ist, wird die Liste nicht bewertet und selbst dann nur nach Bedarf bewertet (dh bis zum gewünschten Index. ) Vorausgesetzt, der Programmierer ist vorsichtig, das Programm wird normal abgeschlossen. Bestimmte Berechnungen können jedoch dazu führen, dass das Programm versucht, eine unendliche Anzahl von Elementen zu bewerten. Zum Beispiel die Länge der Liste anfordern oder versuchen, die Elemente der Liste mit a zu fassen Faltenbetrieb würde dazu führen, dass das Programm entweder nicht beendet oder ausgeführt wird aus dem Gedächtnis.

Als ein weiteres Beispiel kann die Liste aller Fibonacci -Nummern in der geschrieben werden Haskell Programmiersprache als:[14]

 Fibs = 0 : 1 : Zipwith (+) Fibs (Schwanz Fibs) 

In Haskell -Syntax ",":"Vorbereitet ein Element in einer Liste, Schwanz Gibt eine Liste ohne das erste Element zurück und Zipwith Verwendet eine bestimmte Funktion (in diesem Fall Addition), um entsprechende Elemente von zwei Listen zu kombinieren, um ein Drittel zu erstellen.[13]

List-of-Suczesse-Muster

Andere Verwendungen

Im Computer FenstersystemeDas Bild von Informationen auf dem Bildschirm wird von gesteuert Ereignisse aufdecken die den Anzeigecode zum letzten möglichen Moment anführen. Auf diese Weise vermeiden Windowing -Systeme, unnötige Anzeige -Inhaltsaktualisierungen zu berechnen.[15]

Ein weiteres Beispiel für Faulheit in modernen Computersystemen ist Kopieren auf dem Schreiben Seitenzuweisung oder Paging fordern, wo der Speicher nur zugewiesen wird, wenn ein in diesem Speicher gespeicherter Wert geändert wird.[15]

Faulheit kann für Hochleistungsszenarien nützlich sein. Ein Beispiel ist das Unix MMAP Funktion, die liefert Nachfrage gefahren Das Laden von Seiten von der Festplatte, so dass nur diese Seiten in den Speicher geladen werden und der nicht benötigte Speicher nicht zugewiesen wird.

Matlab Geräte Kopieren Sie auf Bearbeiten, wo Arrays, die kopiert werden aus dem Gedächtnis Fehler beim Aktualisieren eines Elements danach statt während des Kopiervorgangs.[16]

Leistung

Die Anzahl der Beta-Reduktionen zur Reduzierung eines Lambda-Terms mit Call-by-Beding ist nicht größer als die Anzahl, die von Call-by-Wert oder erforderlich ist Call-by-Namen die Ermäßigung.[17][18] Und mit bestimmten Programmen kann die Anzahl der Schritte viel kleiner sein, beispielsweise eine bestimmte Familie von Lambda -Begriffen verwenden Kirchliche Ziffern Machen Sie eine unendliche Menge an Schritten mit Call-by-Wert (d. H. Nie vollständig), eine exponentielle Anzahl von Schritten mit Call-by-Namen, aber nur eine Polynomnummer mit Call-by-NED. Call-by-Need verkörpert zwei Optimierungen-wiederholen Sie niemals Arbeit (ähnlich wie Call-by-Wert) und führen Sie niemals unnötige Arbeiten aus (ähnlich wie Call-by-Name).[19] Eine faule Bewertung kann auch zu einer Verringerung des Speicherpflichtzusters führen, da Werte bei Bedarf erstellt werden.[20]

In der Praxis kann eine faule Bewertung im Vergleich zur eifrigen Bewertung erhebliche Leistungsprobleme verursachen. Zum Beispiel ist es bei modernen Computerarchitekturen, eine Berechnung zu verzögern und später durchzuführen, langsamer, als sie sofort durchzuführen. Dies kann durchgelöst werden Strenge Analyse.[19] Eine faule Bewertung kann auch einführen Speicherlecks aufgrund von unbestimmten Ausdrücken.[21][22]

Implementierung

Einige Programmiersprachen verzögern die Bewertung der Ausdrücke standardmäßig, andere bieten an Funktionen oder etwas Besonderes Syntax Bewertung zu verzögern. Im Miranda und HaskellDie Bewertung von Funktionsargumenten wird standardmäßig verzögert. In vielen anderen Sprachen kann die Bewertung verzögert werden, indem die Berechnung mithilfe einer speziellen Syntax explizit suspendiert wird (wie mit Schema "Verzögerung" und "Macht" und Ocaml's "faul" und "Lazy.force") oder allgemeiner durch Wickeln des Ausdrucks in a Thunk. Das Objekt, das eine so explizit verzögerte Bewertung darstellt Faule Zukunft. Raku Verwendet eine faule Bewertung von Listen, sodass man Variablen unendliche Listen zuweisen und sie als Argumente für Funktionen verwenden kann. Im Gegensatz zu Haskell und Miranda verwendet Raku jedoch standardmäßig keine faule Bewertung von arithmetischen Operatoren und Funktionen.[10]

Faulheit und Eifer

Kontrolle der Eifer in faulen Sprachen

In faulen Programmiersprachen wie Haskell ist es jedoch möglich, den Ausdruck nur dann zu bewerten, wenn sie verlangt werden, in einigen Fällen möglich, Code eifriger zu gestalten - oder umgekehrt, um ihn wieder faul zu gestalten, nachdem er eifriger wird. Dies kann durch explizites Codieren von etwas erfolgen, das die Bewertung erzwingt (was den Code mehr eifriger machen kann) oder einen solchen Code zu vermeiden (was den Code faul werden kann). Strikt Die Bewertung impliziert normalerweise das Eifer, aber sie sind technisch unterschiedliche Konzepte.

In einigen Compilern wird jedoch eine Optimierung implementiert, die genannt werden Strenge Analyse, was es dem Compiler in einigen Fällen ermöglicht, zu schließen, dass immer ein Wert verwendet wird. In solchen Fällen kann dies die Wahl des Programmierers erfüllen, ob dieser bestimmte Wert erzwingen soll oder nicht, da die strenge Analyse eine strenge Bewertung erzwingt.

In Haskell bedeutet die Markierungskonstruktorfelder streng, dass ihre Werte immer sofort verlangt werden. Das seq Funktion kann auch verwendet werden, um einen Wert sofort zu fordern und dann weiterzugeben, was nützlich ist, wenn ein Konstruktorfeld im Allgemeinen faul sein sollte. Keine dieser Techniken implementiert jedoch rekursiv Strenge - für diese eine Funktion genannt Deepseq wurde erfunden.

Ebenfalls, Musteranpassung in Haskell 98 ist standhaft streng, also die ~ Qualifikationsspiel muss verwendet werden, um es faul zu machen.[23]

Simulation der Faulheit in eifrigen Sprachen

Java

Im JavaEine faule Bewertung kann durch die Verwendung von Objekten durchgeführt werden, die eine Methode haben, um sie zu bewerten, wenn der Wert erforderlich ist. Der Körper dieser Methode muss den Code enthalten, der zur Durchführung dieser Bewertung erforderlich ist. Seit der Einführung von Lambda -Ausdrücke In Java SE8 hat Java eine kompakte Notation dafür unterstützt. Das folgende Beispiel generisch Die Schnittstelle bietet einen Framework für die faule Bewertung:[24][25]

Schnittstelle Faul<T> {  T bewerten(); } 

Das Faul Schnittstelle mit seinem eval () Methode entspricht der Anbieter Schnittstelle mit seinem erhalten() Methode in der java.util.function Bibliothek.[26]

Jede Klasse, die die implementiert Faul Schnittstelle muss eine bereitstellen bewerten Methode und Instanzen der Klasse können alle Werte tragen, die die Methode benötigt, um eine faule Bewertung zu erreichen. Betrachten Sie beispielsweise den folgenden Code, um 2 zu berechnen und 2 auszudrucken10:

Faul<Ganze Zahl> a = ()-> 1; zum (int i = 1; i <= 10; i++) {  Finale Faul<Ganze Zahl> b = a;  a = ()-> b.bewerten() + b.bewerten(); } System.aus.println( "a =" + a.bewerten() ); 

Im obigen, die Variable a Bezieht sich zunächst auf ein faules, ganzzahliges Objekt, das vom Lambda -Ausdruck erstellt wurde ()-> 1. Die Bewertung dieses Lambda -Ausdrucks entspricht der Erstellung einer neuen Instanz von einem Anonyme Klasse das implementiert Faul mit einem bewerten Methode Rückgabe 1.

Jede Iteration der Schleifenverbindungen a zu einem neuen Objekt, das durch Bewertung des Lambda -Ausdrucks in der Schleife erstellt wurde. Jedes dieser Objekte enthält einen Hinweis auf ein anderes faules Objekt. b, und hat eine bewerten Methode, die aufruft B.eval () zweimal und gibt die Summe zurück. Die Variable b wird hier benötigt, um Javas Anforderung zu erfüllen, dass Variablen, auf die aus einem Lambda -Ausdruck verwiesen wird, endgültig sind.

Dies ist ein ineffizient Memoisieren das Ergebnis früherer Anrufe an bewerten. Es beinhaltet auch beträchtlich Autoboxen und Unboxing. Was möglicherweise nicht offensichtlich ist, ist, dass das Programm am Ende der Schleife a konstruiert hat verlinkte Liste von 11 Objekten und dass alle tatsächlichen Ergänzungen, die an der Berechnung des Ergebniss beteiligt sind A.eval () in der endgültigen Codezeile. Dieser Anruf rekursiv durchquert die Liste, um die erforderlichen Ergänzungen durchzuführen.

Wir können eine Java -Klasse bauen, die sich wie folgt an faule Objekte merkt:[24][25]

Klasse Memo<T> Geräte Faul<T> {  Privatgelände Faul<T> faul;  // Ein fauler Ausdruck setzt Eval ihn auf null  Privatgelände T Memo = Null; // das Memorandum des vorherigen Wertes  Öffentlichkeit Memo( Faul<T> faul ) { // Konstrukteur  Dies.faul = faul;  }  Öffentlichkeit T bewerten() {  wenn (faul ! = Null) {  Memo = faul.bewerten();  faul = Null;  }  Rückkehr Memo;  } } 

Dies ermöglicht es dem vorherigen Beispiel, umgeschrieben zu werden, um weitaus effizienter zu sein. Wo das Original in der Anzahl der Iterationen exponentiell ausgeführt wurde, läuft die memoisierte Version in der linearen Zeit:

Faul<Ganze Zahl> a = ()-> 1; zum (int i = 1; i <= 10; i++) {  Finale Faul<Ganze Zahl> b = a;  a = Neu Memo<Ganze Zahl>( ()-> b.bewerten() + b.bewerten() ); } System.aus.println( "a =" + a.bewerten() ); 

Beachten Sie, dass Javas Lambda -Ausdrücke gerecht sind syntethischer Zucker. Alles, was Sie mit einem Lambda -Ausdruck schreiben können innere Klasse Die Implementierung der Schnittstelle und jeder Verwendung einer anonymen inneren Klasse kann mithilfe einer benannten inneren Klasse neu geschrieben werden, und jede benannte innere Klasse kann auf die äußerste Niststufe verschoben werden.

JavaScript

Im JavaScriptEine faule Bewertung kann mit a simuliert werden Generator. Zum Beispiel die Strom von allen Fibonacci -Zahlen kann geschrieben werden, verwenden Memoisierung, wie:

/**  * Generatorfunktionen geben Generator -Objekte zurück, die eine faule Bewertung neu verehren.  * @return {! Generator <Bigint>} Ein Nicht-Null-Generator von Ganzzahlen.  */ Funktion* Fibonaccinumbers() {  Lassen Memo = [1n, -1n]; // Erstellen Sie den Ausgangszustand (z. B. ein Vektor von "Negafibonacci" -Zahlen)  während (Stimmt) { // unbegrenzt wiederholen  Memo = [Memo[0] + Memo[1], Memo[0]]; // Aktualisieren Sie den Status bei jeder Bewertung  Ertrag Memo[0]; // Ergeben Sie den nächsten Wert und speichern Sie die Ausführung bis zur Wiederaufnahme  } } Lassen Strom = Fibonaccinumbers(); // Erstellen Sie einen faul ausgewerteten Zahlenstrom Lassen First10 = Array.aus(Neu Array(10), () => Strom.nächste().Wert); // Bewerten Sie nur die ersten 10 Zahlen Konsole.Protokoll(First10); // Die Ausgabe ist [0n, 1n, 1n, 2n, 3n, 5n, 8n, 13n, 21n, 34n] 

Python

Im Python 2.x die Angebot() Funktion[27] Berechnet eine Liste von Ganzzahlen. Die gesamte Liste wird im Speicher gespeichert, wenn die erste Zuweisungsanweisung bewertet wird. Dies ist ein Beispiel für eine eifrige oder sofortige Bewertung:

>>> r = Angebot(10) >>> drucken r [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> drucken r[3] 3 

In Python 3.x die Angebot() Funktion[28] Gibt eine zurück Generator Das berechnet Elemente der Liste auf Bedarf. Elemente werden nur dann erzeugt, wenn sie benötigt werden (z. B. wenn print (r [3]) wird im folgenden Beispiel bewertet), daher ist dies ein Beispiel für eine faule oder aufgeschobene Bewertung:

>>> r = Angebot(10) >>> drucken(r) Bereich (0, 10) >>> drucken(r[3])) 3 
Diese Änderung der faulen Bewertung spart die Ausführungszeit für große Bereiche, auf die nie vollständig verwiesen wird, und die Speicherverwendung für große Bereiche, in denen zu irgendeinem Zeitpunkt nur ein oder nur wenige Elemente benötigt werden.

In Python 2.x kann eine Funktion namens verwendet werden xrange () Dies gibt ein Objekt zurück, das die Zahlen im Bereich bei Bedarf generiert. Der Vorteil von Xrange Ist das generierte Objekt immer die gleiche Menge an Speicher.

>>> r = Xrange(10) >>> drucken(r) Xrange (10) >>> lst = [x zum x in r] >>> drucken(lst) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

Ab Version 2.2 manifestiert Python die faule Bewertung durch die Implementierung von Iteratoren (faulen Sequenzen) im Gegensatz zu Tupel- oder Listensequenzen. Zum Beispiel (Python 2):

>>> Zahlen = Angebot(10) >>> Iterator = Iter(Zahlen) >>> drucken Zahlen [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> drucken Iterator  >>> drucken Iterator.nächste() 0 
Das obige Beispiel zeigt, dass Listen bewertet werden, wenn sie aufgerufen werden, aber im Falle eines Iterators wird das erste Element '0' bei Bedarf gedruckt.

.NET Framework

In dem .NET Framework Es ist möglich, eine faule Bewertung mit der Klasse durchzuführen System.lazy.[29] Die Klasse kann leicht ausgenutzt werden F# Verwendung der lazy Schlüsselwort, während das force Die Methode erzwingt die Bewertung. Es gibt auch spezielle Sammlungen wie Microsoft.FSharp.Collections.Seq Dies bietet integrierte Unterstützung für die faule Bewertung.

Lassen Fibonacci = Seq.entfalten (Spaß (x, y) -> Etwas(x, (y, x + y))) (0i,1i) Fibonacci |> Seq.nth 1000 

In C# und vb.net die Klasse System.lazy wird direkt verwendet.

Öffentlichkeit int Summe() {  int a = 0;  int b = 0;   Faul<int> x = Neu Faul<int> (() => a + b);  a = 3;  b = 5;  Rückkehr x.Wert; // Gibt 8 zurück } 

Oder mit einem praktischeren Beispiel:

// rekursive Berechnung der N'th Fibonacci -Nummer Öffentlichkeit int Flunkerei(int n) {  Rückkehr (n == 1)? 1 : (n == 2)? 1 : Flunkerei(n-1) + Flunkerei(n-2); } Öffentlichkeit Leere Hauptsächlich() {  Konsole.Schreiben("Welche Fibonacci -Nummer möchten Sie berechnen?");  int n = INT32.Analysieren(Konsole.Zeile lesen());   Faul<int> Flunkerei = Neu Faul<int> (() => Flunkerei(n)); // Funktion wird vorbereitet, aber nicht ausgeführt  bool ausführen;   wenn (n > 100)  {  Konsole.Schreiben("Dies kann einige Zeit dauern. Möchten Sie diese große Zahl wirklich berechnen? [Y/n]");  ausführen = (Konsole.Zeile lesen() == "y");   }  anders ausführen = Stimmt;       wenn (ausführen) Konsole.Schreiben(Flunkerei.Wert); // Zahl wird nur bei Bedarf berechnet } 

Eine andere Möglichkeit besteht darin, die zu verwenden yield Stichwort:

// eifrige Bewertung  Öffentlichkeit Ienumerable<int> Fibonacci(int x) {  Ilist<int> Fibs = Neu Aufführen<int> ();  int vorläufig = -1;  int nächste = 1;  zum (int i = 0; i < x; i++)  {  int Summe = vorläufig + nächste;  vorläufig = nächste;  nächste = Summe;  Fibs.Hinzufügen(Summe);   }  Rückkehr Fibs; } // Lazy Evaluation  Öffentlichkeit Ienumerable<int> Lazyfibonacci(int x) {  int vorläufig = -1;  int nächste = 1;  zum (int i = 0; i < x; i++)  {  int Summe = vorläufig + nächste;  vorläufig = nächste;  nächste = Summe;  Ertrag Rückkehr Summe;  } } 

Siehe auch

Verweise

  1. ^ Hudak 1989, p. 384
  2. ^ David Anthony Watt; William Findlay (2004). Programmiersprache Designkonzepte. John Wiley und Söhne. S. 367–368. ISBN 978-0-470-85320-7. Abgerufen 30. Dezember 2010.
  3. ^ Reynolds 1998, p. 307
  4. ^ Bentley, Jon Louis. Schreiben effizienter Programme. Prentice-Hall, 1985. ISBN978-0139702440
  5. ^ Wadsworth 1971
  6. ^ Hamer-Hodges, Kenneth (1. Januar 2020). Zivilisation Cyberspace: Der Kampf um die digitale Demokratie. p. 410. ISBN 978-1-95-163044-7. Abgerufen 29. Februar 2020.
  7. ^ Henderson & Morris 1976
  8. ^ Friedman & Wise 1976
  9. ^ Reynolds 1998, p. 312
  10. ^ a b Philip Wadler (2006). Funktional und logikprogrammierung: 8. Internationales Symposium, Flops 2006, Fuji-Susono, Japan, 24.-26. April 2006: Proceedings. Springer. p. 149. ISBN 978-3-540-33438-5. Abgerufen 14. Januar 2011.
  11. ^ "Utility-HT: Data.bool.ht.Private". hackage.haskell.org. Abgerufen 8. Januar 2022.
  12. ^ "Der Haskell 98 -Bericht: Standard -Vorspiel". www.haskell.org. Boolesche Funktionen. Abgerufen 8. Januar 2022.
  13. ^ a b Daniel Le Métayer (2002). Programmiersprachen und Systeme: 11. europäisches Symposium für Programmierung, ESOP 2002, das im Rahmen der gemeinsamen europäischen Konferenzen für Theorie und Praxis der Software, Etaps 2002, Grenoble, Frankreich, 8. bis 12. April 2002: Proceedings. Springer. S. 129–132. ISBN 978-3-540-43363-7. Abgerufen 14. Januar 2011.
  14. ^ a b Verband für Rechenmaschinen; ACM Special Interest Group für Programmiersprachen (1. Januar 2002). Proceedings des ACM Sigplan Haskell Workshops von 2002 (Haskell '02): Pittsburgh, Pennsylvania, USA; 3. Oktober 2002. Verband für Rechenmaschinen. p. 40. ISBN 978-1-58113-605-0. Abgerufen 14. Januar 2011.
  15. ^ a b Faul und spekulative Ausführung Butler Lampson Microsoft Research Opodis, Bordeaux, Frankreich, 12. Dezember 2006
  16. ^ "Aus dem Speicher, wenn Sie vorhandenen Arrays Werte zuweisen? - Matlab -Antworten - Matlab Central".
  17. ^ Niehren, Joachim (1996). "Funktionelle Berechnung als gleichzeitige Berechnung" (PDF). Verfahren des 23. ACM Sigplan -Sigact -Symposiums über Prinzipien der Programmiersprachen - POPL '96: 333–343. doi:10.1145/237721.237801.
  18. ^ Niehren, Joachim (September 2000). "Einheitlicher Zusammenfluss in der gleichzeitigen Berechnung". Journal of Functional Programming. 10 (5): 453–499. doi:10.1017/s0956796800003762. Abgerufen 7. Januar 2022.
  19. ^ a b Stelle, George Widgery (Juli 2019). Call-by-Bedarge-Umwelt-Umwelt (PhD). Universität von New Mexico. S. 11–12. Abgerufen 8. Januar 2022.
  20. ^ Chris Smith (22. Oktober 2009). Programmierung f#. O'Reilly Media, Inc. p. 79. ISBN 978-0-596-15364-9. Abgerufen 31. Dezember 2010.
  21. ^ Launchbury 1993.
  22. ^ Edward Z. Yang. "Space Leak Zoo".
  23. ^ "Lazy Muster Match - Haskellwiki".
  24. ^ a b Grzegorz PiWowarek, Nutzung von Lambda -Ausdrücken für die faule Bewertung in Java, 4Compreta, 25. Juli 2018.
  25. ^ a b Douglas W. Jones, CS: 2820 Notizen, Herbst 2020, Vortrag 25, abgerufen Jan. 2021.
  26. ^ Schnittstelle Suppier <t>, abgerufen im Oktober 2020.
  27. ^ "2. Eingebaute Funktionen-Python 2.7.11 Dokumentation".
  28. ^ "2. Eingebaute Funktionen-Python 3.5.1 Dokumentation".
  29. ^ "Lazy (t) Klasse (System)". Microsoft.

Weitere Lektüre

Externe Links