9 4 1 函式式和命令式類

2021-06-27 14:27:43 字數 2257 閱讀 2691

9.4.1 函式式和命令式類 

在類或者類的建構函式的引數值中的 let 繫結,就像我們在其他 f# **中看到的 let 繫結一樣,也是不可變值;此外,使用 member 關鍵字宣告的屬性,建立的是唯讀屬性(只有 getter)。因此,如果類只引用其他不可變型別的值,那麼,類也不可變。

比方說,在前面的例子中,我們要允許改變客戶的收入,可以有兩種方式:

■以純函式式風格,物件將返回乙個新例項,收入是更新後的,其他所有屬性都是原始值。

■使用命令式風格,收入將是可變字段。

清單 9.15 展示了類的函式式版本(clientf),以及命令式的類,名為classi。

清單 9.15 client 型別的函式式和命令式版本 (f#)

type clientf(name, inc) = 

member x.name = name   | [1]

member x.income = inc   |

member x.withincome(v) =   [2]

new clientf(name, v)

member x.report() = 

printfn "%s %d" name inc

type clienti(name, inc) = 

let mutable inc = inc    [3]

member x.name = name 

member x.income 

with get() = inc      | [4]

and set(v) = inc <- v  |

member x.report() = 

printfn "%s %d" name inc

在函式式版本中,所有屬性都是唯讀的[1]。s 改變客戶的收入,必須建立客戶的乙個新例項,使用 withincome 方法[2]很容易做到,它返回物件的副本,收入為新設定的值。

命令式版本使用 mutable 關鍵字[3],宣告了可更新的字段,儲存收入。宣告字段,我們使用的名字,與值和建構函式的引數相同;新的值隱藏了原來的值,這樣,我們再也不能訪問原始值了。初看起來,這可能很奇怪,但是,可以防止原打算使用當前值(可能已經更改)時,而意外使用了初始值。

在命令式版本中,另乙個值得注意的是用來改變客戶收入的讀/寫屬性,這個屬性是由兩個成員組成,類似於方法宣告。get 成員沒有任何引數,只返回值;而 set 成員只有乙個引數,表示新值的,返回結果為 unit。雖然這個語法與 c# 屬性宣告略有不同,但原理相同。

當改變客戶收入時,兩個類的用法不同,但是,兩個版本得到的結果相同。可以在清單 9.16 中看到 f# interactive 會話,演示如何使用這兩個類。

清單 9.16 client 型別的函式式和命令式程式設計 (f# interactive)

> let joeoriginal = newclientf("joe", 30);; 

val joeoriginal : clientf

> let joeupdated =joeoriginal.withincome(40);;   [1]<-- 建立客戶的新例項

val joeupdated : clientf

> joeupdated.income;; 

val it : int = 40

> let joemutable = newclienti("joe", 30);; 

val joemutable : clienti

> joemutable.income <- 40;;   [2] <-- 修改已有的例項

val it : unit = ()

> joemutable.income;; 

val it : int = 40

當使用不可變的版本時[1],我們把返回的客戶值,用新的名字來儲存。這樣,我們仍然可以訪問原始值。如果在後面的**中,我們不想訪問原始例項,就可以使用值隱藏,兩個值使用相同的名字。在命令式版本中,可以使用讀/寫屬性[2],改變收入。我們使用 <- 運算子,就像在標準的 .net 庫中使用其他宣告的物件一樣。

雖然我們重點在於函式式程式設計,但是,知道如何寫這樣的可變類,有時也是有用的。如果需要公開大段的 f# **給 c# 客戶端,可能要把**包裝到至少乙個類中,因為,這樣更方便從 c# 中使用。在這一點上,可以隨便選擇一種風格:命令式風格,有一些可變型別;純函式式風格,所有都是可變的。從 f# 的觀點來看,第二種方法是更清晰的;但對於開發人員來說,不習慣於處理完全組合不可變型別的庫,可能會發現使用可變狀態的包裝會更容易。

我們幾乎準備展示從 c# 呼叫 f# **的完整示例子了,但還需要先完成物件導向的 f# 功能之旅。

函式式程式設計和命令式程式設計

所謂命令式程式設計,是以命令為主的,給機器提供一條又一條的命令序列讓其原封不動的執行。程式執行的效率取決於執行命令的數量。因此才會出現大o表示法等等表示時間空間複雜度的符號。而函式式語言並不是通常意義上理解的 通過函式的變換進行程式設計 注意到純的函式式語言中是沒有變數的 沒有可以改變的東西,所有的...

命令式和符號式程式設計

命令式程式舉例 def add a,b return a b def fancy func a,b,c,d e add a,b f add c,d g add e,f return g fancy func 1,2,3,4 輸出 在執行語句e add a,b 時,python會做加法運算並將結果儲存...

命令式至函式式隨記(三)

english 函式式的思考中心就是分解問題,舉例來說,計算list長度命令式如下 def length list c 0 for i in list c 1 return c 將之改為函式式是許多介紹函式式的文章會有的範例 def length list return 0 if list else...