当前位置: 首页 > 文档资料 > F# 中文教程 >

F# - 功能( Functions)

优质
小牛编辑
130浏览
2023-12-01

在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