Sök…


Vad är bra med en 0-tuple?

En 2-tuple eller en 3-tuple representerar en grupp relaterade objekt. (Pekar i 2D-utrymme, RGB-värden för en färg, etc.) En 1-tupel är inte särskilt användbar eftersom den lätt kan ersättas med en enda int .

En 0-tuple verkar ännu mer värdelös eftersom den innehåller absolut ingenting . Ändå har det egenskaper som gör det mycket användbart på funktionella språk som F #. Till exempel har typen 0-tuple exakt ett värde, vanligtvis representerat som () . Alla 0-tuples har detta värde så det är i huvudsak en singleton typ. I de flesta funktionella programmeringsspråk, inklusive F #, kallas detta unit .

Funktioner som returnerar void i C # kommer att returnera unit i F #:

let printResult = printfn "Hello"

Kör det i F # interaktiv tolk, så ser du:

val printResult : unit = ()

Detta innebär att värdet printResult är av typen unit , och har värdet () (den tomma tuppeln, varvid en och endast värdet på unit

Funktioner kan också ta unit som en parameter. I F # kan funktioner se ut som om de inte tar några parametrar. Men faktiskt tar de en enda parameter av typen unit . Denna funktion:

let doMath() = 2 + 4

motsvarar faktiskt:

let doMath () = 2 + 4

Det vill säga en funktion som tar en parameter av unit och returnerar int värdet 6. Om du tittar på typsignaturen som den interaktiva F # -utskriften skriver ut när du definierar den här funktionen ser du:

val doMath : unit -> int

Det faktum att alla funktioner tar åtminstone en parameter och returnerar ett värde, även om det värdet ibland är ett "värdelöst" värde som () , betyder att funktionskompositionen är mycket lättare i F # än på språk som inte har unit . Men det är ett mer avancerat ämne som vi kommer till senare. För tillfället, kom ihåg att när du ser unit i en funktionssignatur, eller () i en funktions parametrar, det är 0-tupeltypen som fungerar som sättet att säga "Denna funktion tar, eller returnerar, inga meningsfulla värden."

Uppskjuta körning av kod

Vi kan använda unit som ett funktionsargument för att definiera funktioner som vi inte vill utföra förr senare. Detta är ofta användbart i asynkrona bakgrundsuppgifter, när huvudtråden kanske vill utlösa viss fördefinierad funktionalitet i bakgrundstråden, som att kanske flytta den till en ny fil, eller om en låtbindning inte ska köras omedelbart:

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)

I följande kod definierar vi kod för att starta en "arbetare" som helt enkelt skriver ut värdet den arbetar med varannan sekund. Arbetaren returnerar sedan två funktioner som kan användas för att styra den - en som flyttar den till nästa värde att arbeta med, och en som hindrar den från att fungera. Dessa måste vara funktioner, eftersom vi inte vill att deras kroppar ska köras förrän vi väljer att, annars skulle arbetaren omedelbart flytta till det andra värdet och stänga av utan att ha gjort något.

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

Vi kan sedan starta en arbetare genom att göra

let nextValue, stopOnNextTick = startWorker 12

och arbetet kommer att börja - om vi är i F # interaktiva, kommer vi att se meddelandena som skrivs ut i konsolen varannan sekund. Vi kan sedan springa

nextValue ()

och vi kommer att se meddelandena som indikerar att värdet som bearbetas har flyttat till nästa.

När det är dags att slutföra arbetet kan vi köra

stopOnNextTick ()

funktion, som kommer att skriva ut stängningsmeddelandet och sedan avsluta.

unit är här viktig för att beteckna "ingen ingång" - funktionerna har redan all information de behöver för att arbeta inbyggd i dem, och den som ringer får inte ändra det.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow