8 1 4 在 F 中使用函式列表

2021-06-27 09:17:40 字數 2601 閱讀 1028

8.1.4 在 f# 中使用函式列表

首先,我們宣告乙個表示有關客戶資訊的型別;客戶有很多屬性,因此,用f# 的記錄型別表示最自然的選擇,我們在前一章已經看過。清單 8.4 顯示了型別宣告,和所建立樣本客戶的**。

清單 8.4 client 記錄型別和樣本值 (f# interactive)

> type client =

;;type client = (...)

> let john =

;;val john : client

這裡沒有什麼新東西,我們宣告了乙個型別,並建立它的例項。為使清單更短,我們在宣告型別,和創新值時,都沒有為每個屬性使用單獨一行;在f# 中這是有效的,但必須在屬性之間加上分號。使用輕量級語法,編譯器會自動在行尾加上分號(如果需要分號),但是,當需要分行時,編譯器就無能為力了,必須明確寫上分號。

清單 8.5 完成這個示例。首先,建立測試列表,然後,確定是否提供貸款給前面清單中的樣本客戶(john doe) 。

清單 8.5 執行測試 (f# interactive)

> let tests =    <-- 建立測試列表

[ (fun cl ->cl.criminalrecord = true);

(funcl -> cl.income < 30000);

(funcl -> cl.usescreditcard = false);

(funcl -> cl.yearsinjob < 2) ];;

val tests : (client -> bool) list    [1]

> let testclient(client) =

let issues = tests|> list.filter (fun f -> f (client))   [2]

let suitable =issues.length <= 1                           | 統計問題數,

printfn"client: %s\noffer a loan: %s (issues = %d)" client.name  | 輸出結果

(if (suitable) then "yes" else "no") issues.length;;        |

val testclient : client –> unit

> testclient(john);;

client: john doe

offer a loan: yes (issues = 1)

這是使用lambda 函式寫初始化測試建立列表的常規語法,不必寫出任何型別批註,f# 仍然能夠正確推斷出列表的型別[1]。f# 的型別推斷非常智慧型,使用訪問成員的名字就能推斷出我們想要使用的記錄型別。

在 c# 版本中,我們使用 count 方法統計測試失敗的數量;f# 沒有對等的函式,我們既可以實現乙個,也可以組合其他標準的函式,得到相同的結果。這裡,我們採用第二種方法。首先,我們得到被認為是不安全客戶的測試列表,可以通過使用 list.filter 返回結果為 true 的測試,然後,使用length 屬性,得到問題的數量。

在本節,我們學習了如何設計和使用基本的面向行為的資料結構,函式列表(a list of functions),在 c# 和 f# 中都有。在補充材料「無點式程式設計(point-freeprogramming style)」中,我們會看到清單8.5 中用到的重要的函式技術。在下一節,我們會繼續有關常見做法的討論,就像我們討論兩個物件導向的設計模式和相關函式式結構一樣。

無點式程式設計(point-freeprogramming style)

我們見過很多例子,呼叫高階函式時,不必顯式寫出 lambda 函式,那麼,在清單 8.5 中這樣做也行嗎?程式的這種寫法稱為無點(point-free),因為我們在使用包含值(比如列表)的資料結構時,從來沒有給結構中的值指定任何名字(特定的「點」)。我們用示例來演示已經見過的概念:

[1 .. 10] |> list.map ((+) 100)

places |> list.map (snd >>statusbypopulation)

第一種情況,我們處理乙個數字集合,但是,沒有任何符號表示列表中的值;第二種情況有點類似,只是處理的列表是元組,而且,沒有用任何符號來表示元組或元組中的任何元素。

無點風格之所以可能,是由於有幾項程式設計技術。第一行使用了散函式應用,這種方法是基於有大量引數的函式,建立有必要數量引數的函式。在我們的示例中,我們把中綴運算子 (+) 也看做普通函式。第二行使用了函式組合,這是另一項重要的構建函式技術,不必顯式引用函式處理的值。

現在,我們看一下如何重寫清單8.5 的示例。首先,我們要用管道運算子來重寫 lambda 函式。

把:(fun f ->f client)

重寫成:(fun f-> client |> f)

這兩個函式意思相同。我們幾乎完成,因為管道運算子把 client 作為第乙個引數值,把函式作為第二個引數值。如果我們使用散應用來只指定第乙個引數值(client),將得到乙個函式,引數值為函式 (f),並將它應用到 client:

tests |> list.filter ((|>) client)

無點風格程式設計應始終用在刀刃上。雖然它使**更簡潔、典雅,但是,有時很難閱讀和推理,我們在這裡的演示就很重要。無點風格對於某些領域的函式程式設計是重要的,在第十五章,我們將會看到它在開發特定域語言時的用途。

8 1 4 在 F 中使用函式列表

8.1.4 在 f 中使用函式列表 首先,我們宣告乙個表示有關客戶資訊的型別。客戶端有相當多屬性,所以,最自然的表示將是 f 的記錄型別,我們在前一章中已經看過。清單 8.4 顯示了這個型別宣告,和所建立的示例客戶的 listing 8.4 client record type and sample...

QT 內部使用函式列表

滑鼠事件 void mousepressevent qmouseevent event 單擊 void mousereleaseevent qmouseevent event 釋放 void mousedoubleclickevent qmouseevent event 雙擊 void mousem...

Python在函式中使用 和 接收元組和列表

當要使函式接收元組或字典形式的引數的時候,有一種特殊的方法,它分別使用 和 字首。這種方法在函式需要獲取可變數量的引數的時候特別有用。注意 1 由於在args變數前有 字首,所有多餘的函式引數都會作為乙個元組儲存在args中。如果使用的是 字首,多餘的引數則會被認為是乙個字典的健 值對。2 對於de...