В F # функции работают как типы данных. Вы можете объявить и использовать функцию так же, как и любую другую переменную.
Поскольку функции могут использоваться как любые другие переменные, вы можете —
- Создайте функцию с именем и свяжите это имя с типом.
- Назначьте это значение.
- Выполните некоторые расчеты по этому значению.
- Передайте его в качестве параметра другой функции или подпрограмме.
- Вернуть функцию как результат другой функции.
Определение функции
Функции определяются с помощью ключевого слова let . Определение функции имеет следующий синтаксис —
let [inline] function-name parameter-list [ : return-type ] = function-body
Куда,
-
имя-функции — это идентификатор, который представляет функцию.
-
Параметр-список дает список параметров, разделенных пробелами. Вы также можете указать явный тип для каждого параметра и, если он не указан, компилятор стремится вывести его из тела функции (например, переменных).
-
function-body состоит из выражения или составного выражения, состоящего из ряда выражений. Последнее выражение в теле функции — это возвращаемое значение.
-
return-type — это двоеточие, за которым следует тип, и является необязательным. Если тип возвращаемого значения не указан, компилятор определяет его по окончательному выражению в теле функции.
имя-функции — это идентификатор, который представляет функцию.
Параметр-список дает список параметров, разделенных пробелами. Вы также можете указать явный тип для каждого параметра и, если он не указан, компилятор стремится вывести его из тела функции (например, переменных).
function-body состоит из выражения или составного выражения, состоящего из ряда выражений. Последнее выражение в теле функции — это возвращаемое значение.
return-type — это двоеточие, за которым следует тип, и является необязательным. Если тип возвращаемого значения не указан, компилятор определяет его по окончательному выражению в теле функции.
Параметры функции
Вы перечисляете имена параметров сразу после имени функции. Вы можете указать тип параметра. Тип параметра должен следовать за именем параметра, разделенным двоеточием.
Если тип параметра не указан, он выводится компилятором.
Например —
let doubleIt (x : int) = 2 * x
Вызов функции
Функция вызывается путем указания имени функции, за которым следует пробел, а затем любые аргументы, разделенные пробелами.
Например —
let vol = cylinderVolume 3.0 5.0
Следующие программы иллюстрируют концепции.
Пример 1
Следующая программа вычисляет объем цилиндра, когда радиус и длина заданы как параметры
// 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
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
Volume: 141.372
Пример 2
Следующая программа возвращает большее значение двух заданных параметров —
// 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
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
Max Value: 52
Пример 3
let doubleIt (x : int) = 2 * x printfn "Double 19: %d" ( doubleIt(19))
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
Double 19: 38
Рекурсивные функции
Рекурсивные функции — это функции, которые вызывают сами себя.
Вы определяете рекурсив с помощью комбинации ключевых слов let rec .
Синтаксис для определения рекурсивной функции —
//Recursive function definition let rec function-name parameter-list = recursive-function-body
Например —
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Пример 1
Следующая программа возвращает Фибоначчи от 1 до 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)
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
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
Пример 2
Следующая программа возвращает факториал 8 —
open System let rec fact x = if x < 1 then 1 else x * fact (x - 1) Console.WriteLine(fact 8)
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
40320
Обозначения стрелок в F #
F # сообщает о типе данных в функциях и значениях, используя цепочку обозначений стрелок. Давайте возьмем пример функции, которая принимает один ввод int и возвращает строку. В обозначении стрелки это написано как —
int -> string
Типы данных читаются слева направо.
Давайте возьмем другую гипотетическую функцию, которая принимает два ввода данных int и возвращает строку.
let mydivfunction x y = (x / y).ToString();;
F # сообщает тип данных, используя цепочку обозначений стрелок как —
val mydivfunction : x:int -> y:int -> string
Тип возвращаемого значения представлен крайним правым типом данных в нотации со стрелками.
Еще несколько примеров —
нотация | Имея в виду |
---|---|
плавать → плавать → плавать | Функция принимает два входа с плавающей точкой , возвращает еще один с плавающей точкой . |
int → string → float | Функция принимает int и строковый ввод, возвращает число с плавающей запятой . |
Лямбда-выражения
Лямбда-выражение — это безымянная функция.
Давайте возьмем пример двух функций —
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
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
35
Теперь в приведенном выше примере, если бы вместо определения функции mul мы могли бы использовать лямбда-выражения как —
let applyFunction ( f: int -> int -> int) x y = f x y let res = applyFunction (fun x y -> x * y ) 5 7 printfn "%d" res
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
35
Композиция функций и конвейерная обработка
В F # одна функция может быть составлена из других функций.
В следующем примере показана композиция функции с именем f из двух функций function1 и function2 —
let function1 x = x + 1 let function2 x = x * 5 let f = function1 >> function2 let res = f 10 printfn "%d" res
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
55
F # также предоставляет функцию, называемую конвейерной передачей функций. Конвейерная обработка позволяет объединять вызовы функций как последовательные операции.
Следующий пример показывает, что —
let function1 x = x + 1 let function2 x = x * 5 let res = 10 |> function1 |> function2 printfn "%d" res
Когда вы компилируете и запускаете программу, она выдает следующий вывод: