Ricerca…
Definizione di una funzione con let Binding
I valori possono essere nominati usando let :
# let a = 1;;
val a : int = 1
È possibile utilizzare la sintassi simile per definire una funzione. Fornisci solo parametri aggiuntivi per gli argomenti.
# let add arg1 arg2 = arg1 + arg2;;
val add : int -> int -> int = <fun>
Possiamo chiamarlo così:
# add 1 2;;
- : int = 3
Possiamo passare valori direttamente in questo modo, oppure possiamo passare valori legati a nomi:
# add a 2;;
- : int = 3
La linea che l'interprete ci dà dopo aver definito qualcosa è il valore dell'oggetto con la sua firma del tipo. Quando abbiamo dato un valore semplice legato ad a , è tornato con:
val a : int = 1
Ciò significa che a è un int e il suo valore è 1 .
La firma del tipo della nostra funzione è un po 'più complicata:
val add : int -> int -> int = <fun>
La firma del tipo di add assomiglia a una serie di intarsi e frecce. Questo perché una funzione che accetta due argomenti è in realtà una funzione che accetta solo un argomento, ma restituisce un'altra funzione che accetta l'argomento successivo. Potresti invece leggerlo in questo modo:
val add : int -> (int -> int) = <fun>
Questo è utile quando vogliamo creare al volo diversi tipi di funzioni. Ad esempio, una funzione che aggiunge 5 a tutto:
# let add_five = add 5;;
val add_five : int -> int = <fun>
# add_five 5;;
- : int = 10
# add_five 10;;
- : int = 15
Usando la parola chiave function
La parola chiave function ha automaticamente la corrispondenza del modello quando si definisce il corpo della funzione. Osservalo qui sotto:
# 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"
Funzioni anonime
Poiché le funzioni sono valori ordinari, esiste una comoda sintassi per la creazione di funzioni senza nomi:
List.map (fun x -> x * x) [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Questo è utile, altrimenti dovremmo prima nominare la funzione (vedere let ) per poterla usare:
let square x = x * x
(* val square : int -> int = <fun> *)
List.map square [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Funzioni ricorsive e reciprocamente ricorsive
È possibile definire una funzione per essere ricorsiva con la parola chiave rec , in modo che possa chiamare se stessa.
# 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
È inoltre possibile definire funzioni reciprocamente ricorsive con la parola chiave and , in modo che possano chiamarsi a vicenda.
# 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
Si noti che la seconda funzione non ha la parola chiave req .