F# - 函数



在 F# 中,函数就像数据类型一样。你可以像使用其他变量一样声明和使用函数。

由于函数可以像其他变量一样使用,因此您可以:

  • 创建一个函数,并为其命名并将其名称与类型关联。
  • 为其赋值。
  • 对该值执行一些计算。
  • 将其作为参数传递给另一个函数或子例程。
  • 将函数作为另一个函数的结果返回。

定义函数

函数使用 **let** 关键字定义。函数定义具有以下语法:

let [inline] function-name parameter-list [ : return-type ]
   = function-body

其中:

  • **函数名** 是表示函数的标识符。

  • **参数列表** 给出由空格分隔的参数列表。您还可以为每个参数指定显式类型,如果未指定,编译器会从函数体中推断出来(如变量)。

  • **函数体** 由表达式或由多个表达式组成的复合表达式组成。函数体中的最后一个表达式是返回值。

  • **返回类型** 是冒号后跟一个类型,并且是可选的。如果未指定返回类型,则编译器会从函数体中的最后一个表达式确定它。

函数的参数

您在函数名后列出参数名。您可以指定参数的类型。参数的类型应该跟在参数名后面,用冒号分隔。

如果未指定参数类型,则由编译器推断。

例如:

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

返回类型由链式箭头表示法中最右边的数据类型表示。

更多示例:

表示法 含义
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
广告
© . All rights reserved.