12.5.3 在 f# 中實現計算生成器
在計算表示式塊前面的識別符號,是類的例項,把所需的操作實現成為例項成員。許多操作都已經有了,我們根本不必要提供所有的,最基本的操作用 bind 和 return 成員實現。當 f# 編譯器看到計算表示式,比如清單 12.18 時,會把它轉換為使用這些成員的f# **。f# 示例轉換成這樣:
value.bind(readint(), fun n –>
value.bind(readint(), fun m–>
let add = n + m
let sub = n – m
value.return(n * m) ))
計算的其餘部分轉換成函式,為計算提供了很大的靈活性。bind 成員可能立即呼叫函式,或者不呼叫函式,就返回結果。例如,我們處理選項值時,如果bind 成員的第乙個引數是 none,那麼,道最後結果就是 none,而不管這個函式的結果如何。這樣,bind 操作不會呼叫給定的函式,因為作為引數使用的選項值是不包含實際值;在其他情況下,bind 操作應該有效地記住這個函式(通過把它作為結果的一部分儲存起來),在以後執行。我們會在下一章討論這樣的例子。
我們的示例還表明,多個 let! 結構會轉換成巢狀呼叫 bind 成員。這是因為,作為給這個成員的最後乙個引數值的函式,是連續(continuation),即,表示計算的其餘部分。示例最後呼叫 return 成員,是使用 return 結構建立的。
理解 bind 和 return的型別簽名
各種計算表示式都需要實現的這兩個操作的型別,結構總是相同;唯一的不同,是下面的簽名中泛型型別 m 的變化:
bind : m<'t>* ('t -> m<'r>) -> m<'r>
return : 't -> m<'t>
在前面的示例中,我們使用識別符號 value 來構造計算,這個識別符號就是普通的 f# 值,它是有特定成員物件的例項。在 f# 中,這個物件稱為計算生成器(computation builder)。清單 12.19 實現了乙個簡單的生成器,有兩個必須的成員,我們還需要建立例項 value,在轉換過程中使用。
清單 12.19 為值實現計算生成器 (f#)
member x.bind(value(v), f) =f(v) [1]
member x.return(v) = value(v) [2]
> let readint() = value ;;
生成器實現range功能
range 引數 i,引數 j,引數 z 引數 i是起始位置,引數 j是結束位置,引數 z是在引數1和引數2範圍內的遞增量。如下 def generator i 0,j 0,z 1 range功能的實現 while i 1 遞增時 yield i yield 只保留 當前 數值 i i z pass...
生成器模式 Builder C 實現
意圖 將乙個複雜物件的建立與它的表示分離,使得同樣的構建過程可以建立不同的表示。適用性 1.當建立複雜物件的演算法應該獨立於該物件的組成部分以及它們的裝配方式時。2.當構建過程必須允許被構建的物件有不同的表示時。效果 1.使得可以改變乙個產品的內部表示。2.隱藏產品的內部結構。3.使得構造 和表示 ...
php中的生成器
生成器是另一種可迭代的物件,為了迭代一組資料,可以將資料存入乙個陣列,或者由乙個實現了iterator介面的物件來表示。但兩種方式要麼需要占用大量記憶體,要麼太過於繁瑣。而生成器則是第三種方式。在php中,生成器實際是一種內建類,即generator類。不過使用生成器卻不是直接通過此類的建構函式來構...