5.5.2.1 函式作為引數值和返回值
在第三章,我們已使用過,在 c# 和 f# 中把函式作為引數值,因此,這些基本概念不應該是新的;然而,我們還沒有以這種方式使用過 lambda 函式。lambda 函式是把函式寫成另外函式的引數值的最簡單方法。清單 5.17 提供了乙個簡單的示例。在清單中前面的函式,引數為乙個數和乙個函式,兩次呼叫這個函式,第一次呼叫的結果作為第二次呼叫的引數值。
清單 5.17 在 c# 中 f# 中,函式作為引數值
// c# version
int twice(int input, func f) { [1]
return f(f(input));
var result = twice(2, n => n * n); [2]
// f# version
> let twice (input:int) f =f(f(input));; [3]
val twice : int -> (int -> int) –>int [4]
> twice 2 (fun n -> n * n);; [5]
val it : int = 16
在這個示例中,我們在乙個地方看到所有重要的功能。它顯示如何宣告 c# 方法和 f# 函式,把函式作為引數值([1]和[3]),以及如何使用 lambda 函式呼叫它們([2]和[5])。在 f# 中,我們使用到型別批註,告訴 f# 編譯器,我們只需要整數。我們在下一章可以看到,沒有這個批註,可能自動使函式更為通用。這通常是可取的,但我們希望保持示例盡可能簡單。
在 c# 版本中,twice 是方法,把委託作為引數,而在 f# 版本中,它是函式。當我們看到 f# 簽名時[4],能夠發現,它的構造就是函式型別構造器(箭頭);第二個引數是函式,引數為乙個整數,返回乙個整數,整體型別是有兩個引數的函式。
因為函式就是普通值,因此,我們寫的函式(或 c# 中的方法),也可以把函式作為結果返回。清單 5.18 是乙個函式,引數為乙個數字,返回乙個函式,把這個數字和任何給定的引數值加起來。
清單 5.18 在c# 和 f# 中,把函式作為返回值
c#f#
func adder(int n) {
return (a) => a + n; [1]
func add10 = [3]
adder(10);
var r = add10(15); [5]
// result: r == 25
> let adder(n) =
(fun a -> a + n);; [1]
val adder : int -> int –> int [2]
> let addten = adder 10;; [3]
val addten : (int -> int) [4]
> addten 15;; [5]
val it : int = 25
adder 的引數為乙個整數[1],返回結果為乙個函式。在c# 中,顯式指定了返回型別,是 func 委託,而在 f# 中,返回型別是由型別推斷推導出來的,是函式,其型別為 int -> int。
後面我們會看到,輸出的型別簽名表明,函式的引數為整數,返回函式[2]。如果我們給輸出的簽名加上括號,可以看得更清楚,那麼,會寫成 int-> (int-> int)。
呼叫返回函式的函式(或 c# 的方法)[3],在 c# 中,結果是委託,在 f# 中,是普通的函式。正如輸出的型別簽名所示的[4],引數為整數,返回整數。
呼叫返回的函式(或 c# 中的 func 委託),在 f# 中,我們把它作為普通的函式使用,在 c# 中,把它作為委託呼叫。
清單 5.18 使用乙個簡單的示例,展示了函式作為返回值,但在後面幾章中我們將會看到,從乙個函式返回另乙個函式,更有用。關於這個**,有一件事值得進一步解釋。如果我們看看 f# adder 函式的型別簽名,可以發現,其型別是 int-> int-> int,。這看起來像有兩個引數的函式,而如果像 int-> (int-> int),可能更容易理解。它們的意思是一樣的,因為,f# 和其他函式語言,對有多個引數的函式,通常表示方法不同,[當然是]按通常的物件導向所理解的。
C 結構體作為函式引數 值和引用 和返回值
我們在前面的一些章節中知道,變數作為函式的引數,了解它是值傳遞還是位址傳遞是非常重要的。因為這意味著引數在函式體內的修改是否會影響到該變數本身。不同於陣列,結構是按值傳遞的。也就是說整個結構的內容都複製給了形參,即使某些成員資料是乙個陣列。下面,我們就以乙個例項來證明這一點 程式9.3.1 incl...
函式作為返回值
就像常見的函式一樣,lambda 表示式可以返回乙個函式指標 委託例項 這就意味著我們能夠使用乙個 lambda 表示式來建立並返回另乙個 lambda 表示式。這種行為在很多場景下都是非常有用的。我們先來看下面這個例子 1 func saymyname string language 2 10ca...
引用作為函式引數返回值
說明 1 以引用返回函式值,定義函式時需要在函式名前加 2 用引用返回乙個函式值的最大好處是,在記憶體中不產生被返回值的副本。例如 include float temp 定義全域性變數temp float fn1 float r 宣告函式fn1 float fn2 float r 宣告函式fn2 f...