F# - 功能( Functions)
在F#中,函数的工作方式与数据类型相同。 您可以像任何其他变量一样以相同的方式声明和使用函数。
由于函数可以像任何其他变量一样使用,您可以 -
- 创建一个具有名称的函数,并将该名称与类型相关联。
- Assign it a value.
- 对该值执行一些计算。
- 将其作为参数传递给另一个函数或子例程。
- 作为另一个函数的结果返回一个函数。
定义一个函数 (Defining a Function)
使用let关键字定义函数。 函数定义具有以下语法 -
let [inline] function-name parameter-list [ : return-type ]
= function-body
Where,
function-name是表示函数的标识符。
parameter-list给出由空格分隔的参数列表。 您还可以为每个参数指定显式类型,如果未指定,则编译器倾向于从函数体中推导出它(如变量)。
function-body由表达式或由多个表达式组成的复合表达式组成。 函数体中的最终表达式是返回值。
return-type是冒号,后跟一个类型,是可选的。 如果未指定返回类型,则编译器将从函数体中的最终表达式确定它。
函数的参数
您可以在函数名称后面列出参数的名称。 您可以指定参数的类型。 参数的类型应遵循以冒号分隔的参数名称。
如果未指定参数类型,则由编译器推断。
例如 -
let doubleIt (x : int) = 2 * x
调用函数
通过指定函数名称后跟空格然后用空格分隔的任何参数来调用函数。
例如 -
let vol = cylinderVolume 3.0 5.0
以下程序说明了这些概念。
例子1 (Example 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 (Example 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 (Example 3)
let doubleIt (x : int) = 2 * x
printfn "Double 19: %d" ( doubleIt(19))
编译并执行程序时,它会产生以下输出 -
Double 19: 38
递归函数 (Recursive Functions)
递归函数是自称的函数。
您可以使用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 (Example 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 (Example 2)
以下程序返回factorial 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 expression是一个未命名的函数。
让我们举两个函数的例子 -
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#中,一个函数可以由其他函数组成。
以下示例显示了一个名为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#还提供了一个称为功能pipelining of functions. 流水线操作允许函数调用作为连续操作链接在一起。
以下示例显示 -
let function1 x = x + 1
let function2 x = x * 5
let res = 10 |> function1 |> function2
printfn "%d" res
编译并执行程序时,它会产生以下输出 -
55