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.