Zoeken…


Wat heb je aan een 0-tuple?

Een 2-tuple of een 3-tuple vertegenwoordigen een groep gerelateerde items. (Punten in 2D-ruimte, RGB-waarden van een kleur, enz.) Een 1-tuple is niet erg handig omdat het gemakkelijk kan worden vervangen door een enkele int .

Een 0-tupel lijkt nog nutteloos omdat het absoluut niets bevat. Toch heeft het eigenschappen die het zeer nuttig maken in functionele talen zoals F #. Het type 0-tuple heeft bijvoorbeeld precies één waarde, meestal weergegeven als () . Alle 0-tupels hebben deze waarde, dus het is in wezen een singleton-type. In de meeste functionele programmeertalen, inclusief F #, wordt dit het type unit .

Functies die void in C # retourneren het unit in F #:

let printResult = printfn "Hello"

Voer dat uit in de interactieve F # -interpreter en u ziet:

val printResult : unit = ()

Dit betekent dat de waarde printResult van het type unit is en de waarde () (de lege tuple, de enige waarde van het unit ).

Functies kunnen het type unit als parameter nemen. In F # kunnen functies eruit zien alsof ze geen parameters aannemen. Maar in feite nemen ze een enkele parameter van het type unit . Deze functie:

let doMath() = 2 + 4

is eigenlijk gelijk aan:

let doMath () = 2 + 4

Dat wil zeggen, een functie die één parameter van type- unit en de int waarde 6 retourneert. Als u kijkt naar de typeaanduiding die de F # interactieve interpreter afdrukt wanneer u deze functie definieert, ziet u:

val doMath : unit -> int

Het feit dat alle functies ten minste één parameter nodig hebben en een waarde retourneren, zelfs als die waarde soms een "nutteloze" waarde is zoals () , betekent dat functiesamenstelling een stuk eenvoudiger is in F # dan in talen die niet de type unit . Maar dat is een geavanceerder onderwerp waar we later op zullen ingaan. Onthoud voor nu dat wanneer u unit in een functiehandtekening, of () in de parameters van een functie, dat dit het 0-tuple type is dat dient als de manier om te zeggen: "Deze functie heeft geen betekenisvolle waarden".

Uitvoering van code uitstellen

We kunnen het unit gebruiken als een functieargument om functies te definiëren die we pas later willen uitvoeren. Dit is vaak handig bij asynchrone achtergrondtaken, wanneer de hoofdthread mogelijk een vooraf gedefinieerde functionaliteit van de achtergrondthread wil activeren, zoals misschien verplaatsen naar een nieuw bestand, of als een let-binding niet onmiddellijk moet worden uitgevoerd:

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)

In de volgende code definiëren we code om een "werker" te starten die eenvoudig de waarde waaraan het werkt elke 2 seconden afdrukt. De werker geeft vervolgens twee functies terug die kunnen worden gebruikt om het te besturen - één die het naar de volgende waarde verplaatst om aan te werken, en één die het stopt met werken. Dit moeten functies zijn, omdat we niet willen dat hun lichamen worden uitgevoerd totdat we ervoor kiezen, anders zou de werknemer onmiddellijk naar de tweede waarde gaan en afsluiten zonder iets te hebben gedaan.

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

We kunnen dan een werknemer starten door het te doen

let nextValue, stopOnNextTick = startWorker 12

en het werk zal beginnen - als we in F # interactive zijn, zullen we de berichten elke twee seconden in de console afdrukken. We kunnen dan vluchten

nextValue ()

en we zullen de berichten zien die aangeven dat de waarde waaraan wordt gewerkt, naar de volgende is verplaatst.

Wanneer het tijd is om te werken, kunnen we de

stopOnNextTick ()

functie, die het sluitingsbericht zal afdrukken en vervolgens afsluiten.

Het unit is hier belangrijk om "geen invoer" aan te geven - de functies hebben al alle informatie die ze nodig hebben om in te werken ingebouwd, en de beller mag dat niet veranderen.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow