3

我有一些可變的scala代碼,我試圖用更實用的風格來重寫。這是一段相當複雜的代碼,所以我試圖對它進行重構。我首先想到的是這樣的:最佳功能方法

def iterate(count:Int,d:MyComplexType) = { 
    //Generate next value n 
    //Process n causing some side effects 
    return iterate(count - 1, n) 
} 

iterate(2000000,initialValue) 

這似乎並沒有功能在所有對我來說,因爲我仍然有副作用,在我的代碼混合。我的第二個想法是這樣的:

def generateStream(d:MyComplexType):Stream[MyComplexType] = { 
    //Generate next value n 
    return Stream.cons(n, generateStream(n)) 
} 

for (n <- generateStream(initialValue).take(2000000)) { 
    //process n causing some side effects 
} 

這似乎是一個更好的解決方案給我,因爲至少我從可變值處理代碼隔離我的功能價值代碼。但是,這樣做的內存效率要低得多,因爲我正在生成一個我不需要存儲的大型列表。

這給我留下了3種選擇:

  1. 寫尾遞歸函數,硬着頭皮重構值處理代碼
  2. 使用一個懶惰的名單。這不是一個內存敏感的應用程序(雖然它是性能敏感)
  3. 想出一個新的方法。

我想我真正想要的是一個懶惰的評估序列,我可以在處理它們後丟棄這些值。有什麼建議麼?

+0

n是n的函數嗎?n的函數還是比這個關係更復雜? – sblundy 2010-05-13 18:32:49

+0

是的,n可以僅從d計算,但結果是非確定性的,並且相同的d不會總是產生相同的n。 – dbyrne 2010-05-13 18:46:59

回答

6

請記住,性能關鍵型算法在可變時通常效果更好。所以要小心過早的去優化!

在Scala 2.8中,您可以使用Iterator.iterate創建一個沒有存儲值的無限序列。但我不確定這將是重構代碼以實現更多功能的關鍵步驟。這就是「處理具有副作用的數據」部分,這是棘手的。

你可能把整個事情到迭代塊:

Iterator.iterate(initialState)(x => { 
    // create a new state based upon state x 
}).drop(2000000).next 

,你現在已經通過依次修改您的初始狀態定義無限的處理流。你扔掉前2000000個值(其中一個是初始值),然後得到下一個值(這是2000000的生成值)。用0和x => x + 1試試看它是否有效。

+0

謝謝!這完全是我在找的東西! – dbyrne 2010-05-13 20:43:18

3

我想你要使用​​如果你正在做的是創建一個從0到2000000整數的Seq。它是很好,很懶,至少2.7。

+0

對不起,我認爲我的原始問題不清楚,因爲我簡化了它。我不需要從0到2000000的範圍。Seq由一個複雜的數據結構組成。原始代碼已被修改以反映這一點。 – dbyrne 2010-05-13 18:42:20