F # - funkcje
W języku F # funkcje działają jak typy danych. Możesz deklarować i używać funkcji w taki sam sposób, jak każdej innej zmiennej.
Ponieważ funkcji można używać tak jak innych zmiennych, można -
- Utwórz funkcję z nazwą i skojarz tę nazwę z typem.
- Przypisz mu wartość.
- Wykonaj obliczenia na tej wartości.
- Przekaż go jako parametr innej funkcji lub podprogramu.
- Zwraca funkcję jako wynik innej funkcji.
Definiowanie funkcji
Funkcje są definiowane przy użyciu letsłowo kluczowe. Definicja funkcji ma następującą składnię -
let [inline] function-name parameter-list [ : return-type ]
= function-body
Gdzie,
function-name to identyfikator reprezentujący funkcję.
parameter-listpodaje listę parametrów oddzielonych spacjami. Możesz również określić jawny typ dla każdego parametru, a jeśli nie zostanie określony, kompilator ma tendencję do wywnioskowania go z treści funkcji (podobnie jak zmienne).
function-bodyskłada się z wyrażenia lub wyrażenia złożonego składającego się z wielu wyrażeń. Ostatnim wyrażeniem w treści funkcji jest wartość zwracana.
return-typejest dwukropkiem, po którym następuje typ i jest opcjonalne. Jeśli zwracany typ nie jest określony, kompilator określa go na podstawie końcowego wyrażenia w treści funkcji.
Parametry funkcji
Nazwy parametrów podajesz zaraz po nazwie funkcji. Możesz określić typ parametru. Typ parametru powinien następować po nazwie parametru oddzielonej dwukropkiem.
Jeśli nie określono typu parametru, jest on wywnioskowany przez kompilator.
Na przykład -
let doubleIt (x : int) = 2 * x
Wywołanie funkcji
Funkcja jest wywoływana przez podanie nazwy funkcji, po której następuje spacja, a następnie wszelkie argumenty oddzielone spacjami.
Na przykład -
let vol = cylinderVolume 3.0 5.0
Poniższe programy ilustrują koncepcje.
Przykład 1
Poniższy program oblicza objętość walca, gdy promień i długość są podane jako parametry
// the function calculates the volume of
// a cylinder with radius and length as parameters
let cylinderVolume radius length : float =
// function body
let pi = 3.14159
length * pi * radius * radius
let vol = cylinderVolume 3.0 5.0
printfn " Volume: %g " vol
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Volume: 141.372
Przykład 2
Poniższy program zwraca większą wartość dwóch podanych parametrów -
// the function returns the larger value between two
// arguments
let max num1 num2 : int32 =
// function body
if(num1>num2)then
num1
else
num2
let res = max 39 52
printfn " Max Value: %d " res
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Max Value: 52
Przykład 3
let doubleIt (x : int) = 2 * x
printfn "Double 19: %d" ( doubleIt(19))
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Double 19: 38
Funkcje rekurencyjne
Funkcje rekurencyjne to funkcje, które wywołują siebie.
Definiujesz cykliczne za pomocą let rec kombinacja słów kluczowych.
Składnia do definiowania funkcji rekurencyjnej to -
//Recursive function definition
let rec function-name parameter-list = recursive-function-body
Na przykład -
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Przykład 1
Poniższy program zwraca Fibonacciego 1 do 10 -
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
printfn "Fibonacci %d: %d" i (fib i)
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Fibonacci 1: 1
Fibonacci 2: 2
Fibonacci 3: 3
Fibonacci 4: 5
Fibonacci 5: 8
Fibonacci 6: 13
Fibonacci 7: 21
Fibonacci 8: 34
Fibonacci 9: 55
Fibonacci 10: 89
Przykład 2
Poniższy program zwraca silnię 8 -
open System
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
Console.WriteLine(fact 8)
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
40320
Notacje strzałek w języku F #
F # raportuje o typie danych w funkcjach i wartościach, używając notacji połączonej strzałki. Weźmy przykład funkcji, która przyjmuje jedno wejście int i zwraca ciąg. W notacji strzałkowej jest napisane jako -
int -> string
Typy danych są odczytywane od lewej do prawej.
Weźmy inną hipotetyczną funkcję, która pobiera dwa dane wejściowe typu int i zwraca ciąg.
let mydivfunction x y = (x / y).ToString();;
F # zgłasza typ danych przy użyciu notacji połączonych strzałek jako -
val mydivfunction : x:int -> y:int -> string
Typ zwracany jest reprezentowany przez skrajny prawy typ danych w notacji łańcuchowej.
Więcej przykładów -
Notacja | Znaczenie |
---|---|
float → float → float | Funkcja przyjmuje dwa wejścia typu float , zwraca kolejny float . |
int → string → float | Funkcja przyjmuje dane wejściowe typu int i łańcuch , zwraca wartość zmiennoprzecinkową . |
Wyrażenia lambda
ZA lambda expression to nienazwana funkcja.
Weźmy przykład dwóch funkcji -
let applyFunction ( f: int -> int -> int) x y = f x y
let mul x y = x * y
let res = applyFunction mul 5 7
printfn "%d" res
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
35
W powyższym przykładzie, gdybyśmy zamiast definiować funkcję mul, moglibyśmy użyć wyrażeń lambda jako -
let applyFunction ( f: int -> int -> int) x y = f x y
let res = applyFunction (fun x y -> x * y ) 5 7
printfn "%d" res
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
35
Kompozycja funkcji i rurociągi
W języku F # jedna funkcja może składać się z innych funkcji.
Poniższy przykład przedstawia skład funkcji o nazwie f z dwóch funkcji function1 i function2 -
let function1 x = x + 1
let function2 x = x * 5
let f = function1 >> function2
let res = f 10
printfn "%d" res
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
55
F # udostępnia również funkcję o nazwie pipelining of functions. Pipelining umożliwia łączenie wywołań funkcji w łańcuchy jako kolejne operacje.
Poniższy przykład pokazuje, że -
let function1 x = x + 1
let function2 x = x * 5
let res = 10 |> function1 |> function2
printfn "%d" res
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
55