的實現問題我正在深入研究F#源代碼。F#Seq
在Seq.fs:
// Binding.
//
// We use a type defintion to apply a local dynamic optimization.
// We automatically right-associate binding, i.e. push the continuations to the right.
// That is, bindG (bindG G1 cont1) cont2 --> bindG G1 (cont1 o cont2)
// This makes constructs such as the following linear rather than quadratic:
//
// let rec rwalk n = { if n > 0 then
// yield! rwalk (n-1)
// yield n }
看到上面的代碼後,我測試兩個代碼:
let rec rwalk n = seq { if n > 0 then
yield n
yield! rwalk (n-1)
}
和
let rec rwalk n = seq { if n > 0 then
yield! rwalk (n-1)
yield n
}
我找到的第一個是非常快的,而第二個很慢。如果n = 10000,則在我的機器上花費3秒鐘來生成該序列,因此爲二次時間。
二次時間是合理的,例如,
seq { yield! {1; 2; ...; n-1}; yield n }
轉化爲
Seq.append {1; 2; ...; n-1} {n}
此附加操作應採取線性時間,我猜。在第一個代碼中,附加操作如下所示:seq { yield n; yield! {n-1; n-2; ...; 1} }
,這會花費時間不變。
代碼中的註釋說它是linear
(也許這個線性不是線性時間)。也許這個linear
涉及到使用自定義的實現序列而不是Moand/F#計算表達式(如F#規範中所述,但是規範沒有提及這樣做的原因......)。
有人能澄清這裏的模糊嗎?非常感謝!
(PS,因爲這是一個語言的設計和優化的問題,我還附上哈斯克爾標籤,看看那裏的人有見解。)
+1通過源代碼挖掘 – Brian 2010-11-20 10:44:50