Szukaj…
Definiowanie funkcji za pomocą wiązania let
Wartościom można nadać nazwy za pomocą let :
# let a = 1;;
val a : int = 1
Możesz użyć podobnej składni, aby zdefiniować funkcję. Po prostu podaj dodatkowe parametry dla argumentów.
# let add arg1 arg2 = arg1 + arg2;;
val add : int -> int -> int = <fun>
Możemy to nazwać tak:
# add 1 2;;
- : int = 3
Możemy przekazać wartości bezpośrednio w ten sposób lub możemy przekazać wartości powiązane z nazwami:
# add a 2;;
- : int = 3
Linia, którą podaje nam interpreter po zdefiniowaniu czegoś, jest wartością obiektu z jego podpisem typu. Kiedy nadaliśmy mu prostą wartość powiązaną z a , wróciła z:
val a : int = 1
Co oznacza, że a jest liczbą int , a jej wartość wynosi 1 .
Podpis typu naszej funkcji jest nieco bardziej skomplikowany:
val add : int -> int -> int = <fun>
Podpis typu add wygląda jak wiązka liczb wewnętrznych i strzałek. Jest tak, ponieważ funkcja, która przyjmuje dwa argumenty, jest w rzeczywistości funkcją, która bierze tylko jeden argument, ale zwraca inną funkcję, która przyjmuje następny argument. Zamiast tego możesz przeczytać w ten sposób:
val add : int -> (int -> int) = <fun>
Jest to przydatne, gdy chcemy tworzyć różnego rodzaju funkcje w locie. Na przykład funkcja, która dodaje 5 do wszystkiego:
# let add_five = add 5;;
val add_five : int -> int = <fun>
# add_five 5;;
- : int = 10
# add_five 10;;
- : int = 15
Za pomocą słowa kluczowego funkcji
function kluczowe function automatycznie dopasowuje wzorzec po zdefiniowaniu treści funkcji. Obserwuj to poniżej:
# let foo = function
0 -> "zero"
| 1 -> "one"
| 2 -> "couple"
| 3 -> "few"
| _ -> "many";;
val foo : int -> bytes = <fun>
# foo 0;;
- : bytes = "zero"
# foo 3;;
- : bytes = "few"
# foo 10;;
- : bytes = "many"
# let bar = function
"a" | "i" | "e" | "o" | "u" -> "vowel"
| _ -> "consonant";;
val bar : bytes -> bytes = <fun>
# bar "a";;
- : bytes = "vowel"
# bar "k";;
- : bytes = "consonant"
Funkcje anonimowe
Ponieważ funkcje są zwykłymi wartościami, istnieje wygodna składnia do tworzenia funkcji bez nazw:
List.map (fun x -> x * x) [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Jest to przydatne, ponieważ w przeciwnym razie musielibyśmy najpierw nazwać funkcję (patrz let ), aby móc jej użyć:
let square x = x * x
(* val square : int -> int = <fun> *)
List.map square [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Funkcje rekurencyjne i wzajemnie rekurencyjne
Możesz zdefiniować funkcję, która ma być rekurencyjna za pomocą słowa kluczowego rec , aby mogła się wywoływać.
# let rec fact n = match n with
| 0 -> 1
| n -> n * fact (n - 1);;
val fact : int -> int = <fun>
# fact 0;;
- : int = 1
# fact 4;;
- : int = 24
Można również zdefiniować funkcje wzajemnie rekurencyjne za pomocą słowa kluczowego and , aby mogły się nawzajem wywoływać.
# let rec first x = match x with
| 1 -> 1
| x -> second (x mod 10)
and second x = first (x + 1);;
val first : int -> int = <fun>
val second : int -> int = <fun>
# first 20;;
- : int = 1
# first 12345;;
- : int = 1
Zauważ, że druga funkcja nie ma słowa kluczowego req .