Suche…


Was nützt ein 0-Tupel?

Ein 2-Tupel oder ein 3-Tupel repräsentiert eine Gruppe verwandter Elemente. (Punkte im 2D-Raum, RGB-Werte einer Farbe usw.) Ein 1-Tupel ist nicht sehr nützlich, da es leicht durch ein einzelnes int .

Ein 0-Tupel erscheint noch nutzloser, da es absolut nichts enthält. Es hat jedoch Eigenschaften, die es in funktionalen Sprachen wie F # sehr nützlich machen. Zum Beispiel hat der 0-Tupel-Typ genau einen Wert, normalerweise als () . Alle 0-Tupel haben diesen Wert, es handelt sich also im Wesentlichen um einen Singleton-Typ. In den meisten funktionalen Programmiersprachen, einschließlich F #, wird dies die gerufene unit Typ.

Funktionen, die void in C # zurückgeben, geben den unit in F # zurück:

let printResult = printfn "Hello"

Führen Sie das im interaktiven F # -Interpreter aus, und Sie werden sehen:

val printResult : unit = ()

Dies bedeutet, dass der Wert printResult vom Typ unit ist und den Wert () (das leere Tupel, der einzige Wert des unit ).

Funktionen können den unit als Parameter verwenden. In F # sehen Funktionen möglicherweise so aus, als würden sie keine Parameter übernehmen. Tatsächlich nehmen sie jedoch einen einzigen Parameter der unit . Diese Funktion:

let doMath() = 2 + 4

ist eigentlich gleichbedeutend mit:

let doMath () = 2 + 4

Das heißt, eine Funktion, die einen Parameter der unit und den int Wert 6 zurückgibt. Wenn Sie sich die int ansehen, die der interaktive F # -Interpreter bei der Definition dieser Funktion druckt, wird Folgendes angezeigt:

val doMath : unit -> int

Die Tatsache, dass alle Funktionen mindestens einen Parameter annehmen und einen Wert zurückgeben, auch wenn dieser Wert manchmal ein "nutzloser" Wert wie () , bedeutet, dass die Funktionskomposition in F # viel einfacher ist als in Sprachen, die das nicht haben unit - Typ. Aber das ist ein fortgeschritteneres Thema, auf das wir später noch eingehen werden. Denken Sie im Moment daran, dass, wenn Sie unit in einer Funktionssignatur oder () in den Parametern einer Funktion sehen, dies der 0-Tupel-Typ ist, der dazu dient, zu sagen: "Diese Funktion nimmt oder gibt keine sinnvollen Werte zurück."

Verschiebung der Ausführung von Code

Wir können den unit Typ als Funktionsargument verwenden, um Funktionen zu definieren, die erst später ausgeführt werden sollen. Dies ist häufig bei asynchronen Hintergrundaufgaben nützlich, wenn der Haupt-Thread möglicherweise vordefinierte Funktionen des Hintergrund-Threads auslöst, z. B. das Verschieben in eine neue Datei oder wenn eine Let-Bindung nicht sofort ausgeführt werden soll:

module Time =
    let now = System.DateTime.Now   // value is set and fixed for duration of program
    let now() = System.DateTime.Now // value is calculated when function is called (each time)

Im folgenden Code definieren wir Code zum Starten eines "Arbeiters", der einfach alle 2 Sekunden den Wert ausgibt, an dem er arbeitet. Der Arbeiter gibt dann zwei Funktionen zurück, mit denen er gesteuert werden kann - eine, mit der er zum nächsten Wert bewegt werden kann, und eine, die die Arbeit unterbindet. Dies müssen Funktionen sein, da wir nicht möchten, dass ihre Körper ausgeführt werden, bis wir dies wünschen. Andernfalls würde der Arbeiter sofort zum zweiten Wert wechseln und herunterfahren, ohne etwas getan zu haben.

let startWorker value =
    let current = ref value
    let stop = ref false
    let nextValue () = current := !current + 1
    let stopOnNextTick () = stop := true
    let rec loop () = async {
        if !stop then
            printfn "Stopping work."
            return ()
        else
            printfn "Working on %d." !current
            do! Async.Sleep 2000
            return! loop () }
    Async.Start (loop ())
    nextValue, stopOnNextTick

Wir können dann einen Arbeiter damit anfangen

let nextValue, stopOnNextTick = startWorker 12

und die Arbeit beginnt - wenn wir in F # interaktiv sind, werden die Meldungen alle zwei Sekunden in der Konsole ausgedruckt. Wir können dann rennen

nextValue ()

Die Meldungen zeigen an, dass der Wert, an dem gearbeitet wird, zum nächsten verschoben wurde.

Wenn es Zeit ist, die Arbeit zu beenden, können wir das ausführen

stopOnNextTick ()

Funktion, die die Abschlussnachricht druckt, und beendet sich dann.

Der unit ist hier wichtig, um "keine Eingabe" zu bedeuten - die Funktionen enthalten bereits alle Informationen, die sie zum Arbeiten benötigen, und der Anrufer darf dies nicht ändern.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow