Szukaj…


Czym jest krotka 0?

2-krotny lub 3-krotny reprezentuje grupę pokrewnych przedmiotów. (Punkty w przestrzeni 2D, wartości RGB koloru itp.) 1-krotek nie jest zbyt przydatny, ponieważ można go łatwo zastąpić pojedynczą int .

Krotka 0 wydaje się jeszcze bardziej bezużyteczna, ponieważ nie zawiera absolutnie nic . Ma jednak właściwości, które sprawiają, że jest bardzo przydatny w językach funkcjonalnych, takich jak F #. Na przykład typ krotki 0 ma dokładnie jedną wartość, zwykle reprezentowaną jako () . Wszystkie krotki 0 mają tę wartość, więc zasadniczo jest to singleton. W większości funkcjonalnych języków programowania, w tym F #, nazywa się to typem unit .

Funkcje, które zwracają void w C #, zwracają typ unit w F #:

let printResult = printfn "Hello"

Uruchom to w interaktywnym interpretatorze F #, a zobaczysz:

val printResult : unit = ()

Oznacza to, że wartość printResult jest typu unit i ma wartość () (pusta krotka, jedyna wartość typu unit ).

Funkcje mogą również przyjmować typ unit jako parametr. W języku F # funkcje mogą wyglądać, jakby nie przyjmowały parametrów. Ale w rzeczywistości biorą jeden parametr unit typu. Ta funkcja:

let doMath() = 2 + 4

jest faktycznie równoważny z:

let doMath () = 2 + 4

Oznacza to, że funkcja, która pobiera jeden parametr typu unit i zwraca wartość int 6. Jeśli spojrzysz na podpis typu, który interpreter interaktywny F # drukuje podczas definiowania tej funkcji, zobaczysz:

val doMath : unit -> int

Fakt, że wszystkie funkcje przyjmą co najmniej jeden parametr i zwrócą wartość, nawet jeśli ta wartość jest czasami „bezużyteczną” wartością, taką jak () , oznacza, że składanie funkcji jest o wiele łatwiejsze w języku F # niż w językach, które nie mają typ unit . Ale to jest bardziej zaawansowany temat, do którego przejdziemy później. Na razie pamiętaj tylko, że gdy widzisz unit w sygnaturze funkcji lub () w parametrach funkcji, jest to typ krotki 0, który służy jako sposób na powiedzenie „Ta funkcja przyjmuje lub zwraca żadne znaczące wartości”.

Odroczenie wykonania kodu

Możemy użyć typu unit jako argumentu funkcji, aby zdefiniować funkcje, które nie będą wykonywane później. Jest to często przydatne w asynchronicznych zadaniach w tle, gdy główny wątek może chcieć uruchomić pewną predefiniowaną funkcjonalność wątku w tle, na przykład przenosząc go do nowego pliku lub jeśli nie należy natychmiast uruchamiać wiązania let:

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)

W poniższym kodzie definiujemy kod uruchamiający „pracownika”, który po prostu drukuje wartość, nad którą pracuje co 2 sekundy. Następnie pracownik zwraca dwie funkcje, których można użyć do sterowania nim - jedną, która przesuwa ją do następnej wartości, nad którą ma pracować, i jedną, która zatrzymuje ją od działania. Muszą to być funkcje, ponieważ nie chcemy, aby ich ciała były wykonywane, dopóki tego nie zrobimy, w przeciwnym razie pracownik natychmiast przejdzie do drugiej wartości i zamknie się, nie robiąc nic.

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

Następnie możemy rozpocząć pracę od pracownika

let nextValue, stopOnNextTick = startWorker 12

i praca się rozpocznie - jeśli będziemy w interaktywnej F #, co dwie sekundy będziemy wyświetlać komunikaty w konsoli. Możemy wtedy uruchomić

nextValue ()

i zobaczymy komunikaty wskazujące, że opracowywana wartość została przeniesiona do następnej.

Kiedy nadejdzie czas zakończenia pracy, możemy uruchomić

stopOnNextTick ()

funkcja, która wydrukuje komunikat zamknięcia, a następnie wyjdzie.

Typ unit jest tutaj ważny, aby oznaczać „brak danych wejściowych” - funkcje mają już wbudowane wszystkie informacje potrzebne do pracy, a osoba dzwoniąca nie może tego zmienić.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow