3 3 4 處理函式式列表

2021-08-25 18:51:26 字數 2194 閱讀 5178

3.3.4 處理函式式列表

到目前為止,我們已經討論了函式式列表型別的外表特徵,以及如何在 c# 中實現。現在是時候編寫一些實際的**使用函式式程式設計。例如,我們要在 c# 中實現一種方法 sumlist(或 f # 中的 sumlist 函式),對列表中的數求和。

用 c# 求和列表

如果您習慣於在 c# 中使用命令式程式設計,並使用過標準的 .net 陣列或來自 system.collections.generic 的 list 類,或許會建立乙個變數 total,並初始化為零,寫乙個 for 迴圈,在所有的數上迭代,把每乙個元素加到 total 上(就像 total + = list[i])。(或者,可以用 foreach 迴圈,這是乙個語法糖,使之更易用,但概念仍是相同的。)

但是,使用函式式列表,不允許通過索引訪問元素,不支援 foreach,那我們又該如何做呢[4]?為此,我們可以使用遞迴,編寫乙個方法,處理兩種情況的列表:為空和 cons cell。可以在清單 3.15 中看到 c# 版本的 sumlist **。

listing 3.15 summing list elements (c#)

int sumlist(funclist numbers)

var list = funclist.cons(1, funclist.cons(2,

funclist.cons(3, funclist.cons(4,

funclist.cons(5, funclist.empty())))));

int sum = sumlist(list);

console.writeline(sum);

sumlist 方法首先檢查列表是否為空。如果非空,執行匹配 cons cell 的分支,它以遞迴方式呼叫 sumlist 計算

尾(這個列表的)中元素之和,並將此結果加到儲存在頭的值中。此遞迴呼叫執行直到,到達列表的結尾,並在尾中找到乙個空列表為止。對於空列表,函式終止,並返回零。

接下來,我們建立了使用來自非泛型的 funclist 類這個工具方法 cons 和 empty 。這個建立有點麻煩,但你可以實現乙個方法,使之不那麼困難,從通常的 .net 集合建立函式式列表。

用 f# 求和列表

現在,你知道了這個**在 c# 中看起來是怎樣的,讓我們嘗試在 f# 中實現相同的功能。清單 3.16 顯示了 乙個f# 函式 sumlist 和幾個為測試用的 f# interactive 命令。

listing 3.16 summing list elements (f# interactive)

> let rec sumlist list =

match list with

| -> 0

| head::tail -> head + sumlist(tail)

;;val sumlist : int list -> int

> let list = [ 1 .. 5 ];;

val list : int list

> sumlist(list);;

val it : int = 15

如果你與前面的 c# 實現的**比較,就會發現很多相似之處。在以前的情況中,有兩個分支,乙個是為空列表,乙個用於 cons cell。第二個分支再次使用遞迴實現。顯著的區別是,在 f# 中,我們可以使用模式匹配選擇執行路徑。模式匹配也會從 cons cell 中提取值,因此,執行一旦進入第二個分支, head 和 tail 的值都已可用。這增加了**的穩健:不能使用沒有被模式匹配的值。這聽起來微不足道,但它可以防止**意外地試圖訪問(不存在) 空列表的元素。在函式語言中模式匹配是一種自然的結構,但在 c# 中沒有對應的功能,所以我們必須使用條件運算子(?:)來實現相同的行為。

此外,f# 型別推斷能再次幫助我們:不必要**中的任意位置顯式指定型別。正如你能看到的,它正確地推斷出,該函式取乙個整數列表,並返回乙個整數。推理演算法使用的根據,測試 list 值是乙個空列表,還是cons cell,推斷出值的型別是列表。因為,乙個分支將返回 0,它知道整個函式返回乙個整數。因為,我們要將列表中的元素加在一起,可以推斷出這個引數值是乙個包含整數的列表。

在這一節中使用的遞迴是重要的,但是,顯式使用遞迴寫出一切就很難。在下一節中,我們將介紹一種機制,可以隱藏**中困難的遞迴部分。

[4] 我們可以在**中,新增對 foreach 語句的支援,對於現實的 funclist 型別,這樣做是值得的。

3 3 4 處理函式式列表

3.3.4 處理函式式列表 到目前為止,我們已經討論了函式式列表型別的外表特徵,以及如何在 c 中實現。現在是時候編寫一些實際的 使用函式式程式設計。例如,我們要在 c 中實現一種方法 sumlist 或 f 中的 sumlist 函式 對列表中的數求和。用 c 求和列表 如果您習慣於在 c 中使用...

6 7 處理列表

6.7 處理列表 在第三章,我們討論過列表,學習了顯式使用遞迴和模式匹配處理列表。還用 c 實現了函式式列表型別。第 4 章的演示樣例應用程式就以這樣的方式使用列表,可是要注意,顯式寫列表處理並不有用。在這一章。將用到遞迴模式,因此,你可能已經知道我們下一步要討論什麼了。我們能夠使用高階函式來處理列...

6 3 1 處理計畫列表

6.3.1 處理計畫列表 在前面的示例中,因為我們想要列印新的計畫,因此,使用了命令式的 for 迴圈 如果想要建立包含新的計畫列表,可以使用 list.map 函式,就像這樣 let newschedules list.map fun s s mapschedule fun d d.adddays...