F# - 函数


在 F# 中,函数的工作方式类似于数据类型。您可以像任何其他变量一样声明和使用函数。

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

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

定义函数

函数是使用let关键字定义的。函数定义具有以下语法 -

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

在哪里,

  • function-name是代表函数的标识符。

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

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

  • 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

以下程序返回 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
整型 → 字符串 → 浮点数 该函数接受一个int和一个字符串输入,返回一个float

拉姆达表达式

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