F # Lazy Bewertung vs Non-Lazy

8

Ich fange gerade mit F # an, also sei bitte freundlich, wenn das einfach ist.

Ich habe gelesen, dass eine als faul markierte Funktion nur einmal ausgewertet und dann zwischengespeichert wird. Zum Beispiel:

%Vor%

Im Vergleich zu dieser Version, die bei jedem Aufruf tatsächlich ausgeführt wird:

%Vor%

Darauf basierend sollten alle Funktionen faul gemacht werden? Wann möchtest du nicht? Dies kommt von Material in dem Buch "Beginning F #" .

    
Yuck 13.07.2011, 18:35
quelle

3 Antworten

13

Zunächst kann es hilfreich sein, zu beachten, dass keines der von Ihnen definierten Dinge eine Funktion ist - eagerFunc und theValue sind Werte vom Typ int und lazyFunc ist ein Wert vom Typ Lazy<int> . Gegeben

%Vor%

und

%Vor%

Der Ausdruck 1 + 1 wird nicht mehr als einmal ausgewertet, egal wie oft eagerTwo verwendet wird. Der Unterschied besteht darin, dass 1 + 1 einmal genau ausgewertet wird, wenn definierend eagerTwo ist, aber höchstens bewertet wird, wenn lazyTwo wird verwendet (es wird beim ersten Zugriff auf die Eigenschaft Value ausgewertet und dann zwischengespeichert, damit die weitere Verwendung von Value nicht neu berechnet werden muss). Wenn auf lazyTwo s Value niemals zugegriffen wird, wird sein Körper 1 + 1 nie ausgewertet.

Normalerweise werden Sie keinen großen Nutzen darin sehen, faule Werte in einer strengen Sprache wie F # zu verwenden. Sie fügen einen geringen Overhead hinzu, da beim Zugriff auf die Eigenschaft Value überprüft werden muss, ob der Wert bereits berechnet wurde. Sie können Ihnen ein wenig Rechenzeit einsparen, wenn Sie etwas wie let lazyValue = lazy someVeryExpensiveCalculationThatMightNotBeNeeded() haben, da die teure Berechnung nur stattfindet, wenn der Wert tatsächlich verwendet wird. Sie können auch einige Algorithmen beenden lassen, die es sonst nicht geben würde, aber das ist kein großes Problem in F #. Zum Beispiel:

%Vor%     
kvb 13.07.2011, 18:48
quelle
6

Wenn Funktionsausführungen Nebeneffekte haben und es wichtig ist, die Nebenwirkungen jedes Mal zu sehen, wenn die Funktion aufgerufen wird (etwa wenn sie eine I / O-Funktion umschließt), sollte sie nicht faul sein.

Es gibt auch Funktionen, die so trivial sind, dass die Ausführung jedes Mal schneller ist als das Zwischenspeichern des Wertes -

    
antlersoft 13.07.2011 18:41
quelle
5

let eagerFunc = (1 + 1) ist eine gebundene Bindung und wird nur einmal ausgeführt. let eagerFunc() = (1 + 1) ist eine Funktion, die unit (nichts) akzeptiert und eine int zurückgibt. Es wird jedes Mal ausgeführt, wenn es aufgerufen wird. In gewisser Hinsicht ist jede Funktion faul, dh sie wird nur ausgeführt, wenn sie aufgerufen wird. Das lazy -Schlüsselwort (und System.Lazy , das es zurückgibt) führt jedoch den Ausdruck / die Funktion aus, die ihm höchstens einmal gegeben wurde. Nachfolgende Aufrufe der Eigenschaft Value geben das zwischengespeicherte Ergebnis zurück. Dies ist nützlich, wenn die Berechnung des Werts teuer ist.

Viele Funktionen sind nicht zur Verwendung mit lazy geeignet, da sie entweder nicht deterministisch sind (bei jedem Aufruf ein anderes Ergebnis liefern können) oder parametrisiert sind. Natürlich ist es möglich, eine vollständig angewendete Version dieser Funktionen zu verwenden (ein Wert wird für jeden Parameter mitgeliefert), aber im Allgemeinen ist die Variabilität erwünscht.

    
Daniel 13.07.2011 18:42
quelle

Tags und Links