2016-03-26 9 views
2

Ich habe die folgende Berechnung Ausdruck Builder:Null und Kombinieren in Computation Expression

type ExprBuilder() = 
    member this.Return(x) = 
     Some x 

let expr = new ExprBuilder() 

ich den Zweck der Methoden Return verstehen, Null und Kombinieren, aber ich verstehe nicht, was ist die Differenz zwischen Ausdrücken unten dargestellt:

let a = expr{ 
    printfn "Hello" 
    return 1 
} // result is Some 1 

let c = expr{ 
    return 1 
    printfn "Hello" 
} // do not compile. Combine method required 

ich verstehe nicht, warum auch im ersten Fall Null Methode in nicht erforderlich für printfn Aussage?

Antwort

4

Im ersten Ausdruck führen Sie einige Berechnungen, die Wert 1 ergibt, und das ist es. Sie brauchen keine Zero darin, weil Zero nur für return -less Ausdrücke benötigt wird (deshalb heißt es "Null" - es ist, was da ist, wenn nichts da ist), und Ihr Ausdruck hat eine return.

Um speziell Ihre Frage zu beantworten, ist Zero nicht erforderlich "für die printfn Anweisung", weil nicht jede Zeile innerhalb des Ausdrucks umgewandelt wird. Beim Kompilieren von Berechnungsausdrücken bricht der Compiler sie an "speziellen" Punkten auf, wie beispielsweise let!, do!, return usw., wobei der gesamte Rest des Codes zwischen diesen Punkten intakt bleibt. In diesem Fall wird Ihr printfn Aufruf nur Teil des Codes, der vor dem return ausgeführt wird.

Im zweiten Ausdruck, führen Sie zwei Berechnungen: Der erste Wert Ergebnisse in 1 und zweiten Ergebnisse in Zero (die implizit angenommen wird, wenn die Expression eines return fehlt). Der gesamte Berechnungsausdruck kann jedoch nicht zwei Rückgabewerte haben, sondern einen. Um also die Ergebnisse der beiden Berechnungen zusammen zu bringen (man könnte sagen kombinieren sie), benötigen Sie die Combine Methode.

Neben Combine und Zero müssen Sie auch Delay implementieren, damit dies funktioniert. Mehrteilige (d. H. "Kombinierte") Berechnungen werden auch in Delay eingepackt, um es dem Builder zu ermöglichen, die Bewertung zu verschieben und möglicherweise einige Teile innerhalb der Combine Implementierung zu löschen.

Ich empfehle this introduction von Scott Wlaschin, speziell part 3 about Delay and Run.