2015-10-12 25 views
2

作爲使用策略模式的項目的一部分,我試圖編寫一個函數,該函數創建一個函數,該函數在每次應用時返回無限序列的下一個值。F#Seq.next - 什麼是正確的模式?

let GetNext<'T> (enumerator:System.Collections.Generic.IEnumerator<'T>) = 
    let n = enumerator.MoveNext() 
    enumerator.Current 

let FunctionFactory<'T> = 
    let s = 0.0 |> Seq.unfold (fun i -> Some(i, if 0.0 = i then 1.0 else 0.0)) 
    let enumerator = s.GetEnumerator() 
    (fun (ignoredParam:'T) -> GetNext enumerator) 

我想FunctionFactory看起來像這樣:目前我使用這個狡猾的GetNext功能做

let FunctionFactory<'T> = 
    let s = 0.0 |> Seq.unfold (fun i -> Some(i, if 0.0 = i then 1.0 else 0.0)) 
    (fun (ignoredParam:'T) -> Seq.next s) 

ignoredParam在其他功能使用的通過相同的戰略模式並依賴於它提供的上下文。由於這看起來很糟糕,所以我有兩個問題。爲什麼沒有Seq.next?什麼是正確/優雅的方式實施各種各樣的序列表達式,可以注入這樣的策略框架,如這個?

以下是Fyodor Soikin的回答編輯 - 序列表達式現在很吸引我,因爲它們幫助我思考我正在看的問題。我想用更復雜的輸入序列來構建這種模式,而不是可變的命令式樣代碼。

回答

5

你有沒有注意到你永遠不會處理枚舉? 這就是爲什麼沒有Seq.next:它的使用需要不完善的設計。

至於第二個問題,目前還不完全清楚你試圖實施什麼樣的「這個」。就我所能從代碼中搜集的內容來看,你試圖產生一個「有狀態的過程」,它會產生1.0或0.0,每次調用時都會進行切換。對?

如果是這樣,我會通過一個可變的值來做到這一點。比序列開銷少很多:

let FunctionFactory<'T> = 
    let mutable flag = true 
    fun (_:'T) -> 
     flag <- not flag 
     if flag then 1.0 else 0.0 
+0

爲什麼我需要配置枚舉器?當我刪除所有對返回函數的引用時,是不是垃圾回收?我很欣賞這種實現工廠功能的替代方式。我正在設計我的應用程序,目的是在這個簡單的例子之外定義大量的序列表達式,我會更新這個問題來反映這個問題,它會改變你對第二部分的答案嗎? –

+0

在這種特殊情況下,當然,統計員將由GC接收。但是如果你想一般地使用序列,你必須正確地執行合同,而合同清楚地表明,調查員必須被確定性地銷燬。 –

+0

謝謝,我不喜歡它,但是當我瀏覽庫實現時它是有意義的,現在我看到有多少Seq。*函數就像一個範圍枚舉:https://github.com/fsharp/fsharp/blob /master/src/fsharp/FSharp.Core/seq.fs –

相關問題