F# - 函数
在 F# 中,函数的工作方式类似于数据类型。 您可以像任何其他变量一样声明和使用函数。
由于函数可以像任何其他变量一样使用,因此您可以 −
- 创建一个具有名称的函数,并将该名称与类型相关联。
- 为其指定一个值。
- 对该值执行一些计算。
- 将其作为参数传递给另一个函数或子例程。
- 将一个函数作为另一个函数的结果返回。
定义函数
函数是使用let关键字定义的。 函数定义具有以下语法 −
let [inline] function-name parameter-list [ : return-type ] = function-body
其中,
function-name是代表函数的标识符。
parameter-list 给出以空格分隔的参数列表。 您还可以为每个参数指定显式类型,如果未指定,编译器往往会从函数体(如变量)中推断出它。
function-body 由一个表达式或由多个表达式组成的复合表达式组成。 函数体中的最后一个表达式就是返回值。
return-type 是一个冒号后跟一个类型,并且是可选的。 如果未指定返回类型,则编译器根据函数体中的最终表达式确定它。
函数的参数
在函数名称后面列出参数名称。 您可以指定参数的类型。 参数类型应跟在参数名称后面,并用冒号分隔。
如果未指定参数类型,则由编译器推断。
例如 −
let doubleIt (x : int) = 2 * x
调用函数
通过指定函数名称后跟一个空格,然后指定由空格分隔的任何参数来调用函数。
例如 −
let vol = cylinderVolume 3.0 5.0
以下程序说明了这些概念。
示例 1
以下程序在给定半径和长度作为参数时计算圆柱体的体积
// 该函数计算体积 // 以半径和长度为参数的圆柱体 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
以下程序返回 Fibonacci 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
返回类型由链式箭头表示法中最右边的数据类型表示。
更多示例 −
符号 | 含义 |
---|---|
float → float → float | 该函数接受两个float输入,返回另一个float。 |
int → string → float | 该函数接受一个int和一个string输入,返回一个float。 |
Lambda 表达式
lambda 表达式 是一个未命名函数。
让我们举两个函数的例子 −
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,,我们可以使用 lambda 表达式作为−
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# 中,一个函数可以由其他函数组合而成。
下面的示例显示了由两个函数 function1 和 function2 组成的名为 f 的函数 −
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
当您编译并执行该程序时,它会产生以下输出 −
55