Поиск…
Определение функции с помощью привязки
Значениям могут присваиваться имена, используя let :
# let a = 1;;
val a : int = 1
Вы можете использовать аналогичный синтаксис для определения функции. Просто укажите дополнительные параметры для аргументов.
# let add arg1 arg2 = arg1 + arg2;;
val add : int -> int -> int = <fun>
Мы можем назвать это следующим образом:
# add 1 2;;
- : int = 3
Мы можем передавать значения непосредственно так, или мы можем передавать значения, связанные с именами:
# add a 2;;
- : int = 3
Линия, которую интерпретатор дает нам после того, как мы что-то определяем, - это значение объекта с его сигнатурой типа. Когда мы дали ему простое значение, связанное с a , оно вернулось с:
val a : int = 1
Это означает, что a является int , а его значение равно 1 .
Типичная подпись нашей функции немного сложнее:
val add : int -> int -> int = <fun>
Типичная подпись add выглядит как пучок ints и стрелок. Это связано с тем, что функция, которая принимает два аргумента, фактически является функцией, которая принимает только один аргумент, но возвращает другую функцию, которая принимает следующий аргумент. Вместо этого вы могли бы прочитать это следующим образом:
val add : int -> (int -> int) = <fun>
Это полезно, когда мы хотим создавать разные виды функций «на лету». Например, функция, которая добавляет 5 ко всему:
# let add_five = add 5;;
val add_five : int -> int = <fun>
# add_five 5;;
- : int = 10
# add_five 10;;
- : int = 15
Использование ключевого слова function
Ключевое слово function автоматически имеет соответствие шаблонов, когда вы определяете тело своей функции. Обратите внимание на это ниже:
# 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"
Анонимные функции
Поскольку функции являются обычными значениями, существует удобный синтаксис для создания функций без имен:
List.map (fun x -> x * x) [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Это удобно, поскольку в противном случае мы должны были бы сначала назвать функцию (см. Let ), чтобы иметь возможность ее использовать:
let square x = x * x
(* val square : int -> int = <fun> *)
List.map square [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)
Рекурсивные и взаимно рекурсивные функции
Вы можете определить функцию, которая будет рекурсивной, с ключевым словом rec , поэтому она может вызывать себя.
# 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
Кроме того, можно определить взаимно рекурсивные функции с and ключевым словом, так что они могут звонить друг друг.
# 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
Обратите внимание, что вторая функция не имеет ключевого слова req .