3

在過去的幾天裏,我研究了LazyEvaluation,主要是在性能方面,想知道LazyEvalutaion的性能優勢在哪裏出現LazyEvalutaion的性能優勢究竟在哪裏出現?

這是這麼不清楚我閱讀各種文章,但極少數,包括

What are the advantages of Lazy Evaluation?

這是指語法樹的評價。如果您懶惰地評估了語法樹 (即需要它所代表的值),則您的 必須通過整個計算的上一步完成其 。這是懶惰評估的開銷。但是,還有 兩個優點。 1)你將不必evaulate樹如果 結果是從未使用過

JavaScript中,例如,實施如果語法。

if(true) 
{ 
    //to evaluate 
} 
else 
{ 
    //not to evaluate 
} 

在這種普通的情況下,我們沒有任何性能問題。

要評估完成,不進行評估,在語法樹中將被忽略。

然而,在一些遞歸循環,例如,Tak function AKA Tarai function

函數德(X,Y,Z){ 返回(X < = Y)? y: tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y)); }

由於JS的渴望評估戰略評估函數(參數)的必然性, 的如果 - 其他 - 不被評估控制不再有效,並且德功能爆炸的評估步驟的數目。

反對躍躍欲試評估(JS或其他語言)的這一缺點,哈斯克爾可以評估沒有問題,因爲它是,有些JS庫如lazy.js勝過像函數式編程,其中遞歸列表中的特定區域需要管理。

除了無限的列表,我明白這是LazyEvaluation性能優勢的確切原因。我對麼?

+2

對於haskell程序員來說,性能實際上是懶惰評估中棘手的部分之一。真正的好處在於表達能力,允許程序員以多種不同的方式設計解決方案(例如,我想將這些代碼表示爲無限列表),並且能夠將解決方案拆分爲可輕鬆組成的部分,靈活在一個嚴格的語言評估問題將決定你如何構建你的代碼。你也需要懶惰才能真正擁有一種「聲明式」的語言,並且(理想情況下)一旦你擁有了你從未想過的「評估」。 – jberryman

+1

@jberryman,感謝您的輸入。我同意。對於最後一部分,「聲明式」,除了懶惰,我認爲我們真的需要通過事件流以FRP方式將語言與IO結合起來。順便說一下,我喜歡你網站上的照片。 –

回答

3

我認爲你有正確的想法。

雖然我不認爲你需要所有的複雜性。想象一下,JavaScript是

if (veryExpensiveFunction()) { 
    doThis(); 
} else { 
    doThat(); 
} 

現在想象一下veryExpensiveFunction已經實現。

function veryExpensiveFunction() { 
    return true || evenMoreExpensiveFunction(); 
} 

如果JavaScript的,因爲||是懶惰的(僅限於評估是否需要第二個參數),這將返回速度非常快(因爲true,沒錯,是真的!)。如果它被實施,而不是像

function veryExpensiveFunction() { 
    var a = true; 
    var b = evenMoreExpensiveFunction(); // forces the evaluation 

    return a || b; 
} 

這將需要年齡來評估,因爲你已經不必要地評估參數。現在想象一下適用於||的魔法適用於每一種功能(即懶惰的語言),你可以想象懶惰可能帶來的那種性能優勢。

在您的例子

function tak(x,y,z){ return (x <= y) ? y : tak(tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y)); } 

讓我們想象一下,一切都懶。

var a = tak(1,2,3); 

這什麼都不做(沒什麼需要評估)。沒有使用a,所以沒有評估。

var a = tak(1,2,3); 
console.log(a); 

現在我們有能力推動tak的評估。當我們需要得到結果時進行評估,我們首先將值替換(用它們的參數替換變量)。然後我們評估條件,然後評估我們需要的條件。

console.log((1 <= 2) ? 2 : tak(tak(1-1, 2, 3), tak(2-1, 1, 3), tak(3-1, 1, 2)); 
console.log( true ? 2 : tak(tak(1-1, 2, 3), tak(2-1, 1, 3), tak(3-1, 1, 2)); 
console.log(2); 

在這個例子中(假設我沒有作出任何可怕的拼寫錯誤),那麼我們就需要評估任何東西比其他的參數也沒有遞歸調用製成。

+0

謝謝@Jeff Foster。我沒有注意到||目前爲止很懶,所以非常翔實。然而,這種技術不能用於遞歸函數,因爲我們已經有了通過(參數)來調用函數,並且它立即被計算出來,是正確的嗎? –

+0

不可以。只根據需要進行評估。爲了推動評估,有人必須要求遞歸函數的結果。 –

+0

嗯,這還不是很清楚。是否可以使用lazy ||寫下tak函數的代碼技術,如果你不介意。 –