2012-01-10 34 views
6

在大多數編程語言中,傳遞給函數的參數在之前被評估爲,函數使用它們,也就是說,它們被急切地評估。爲什麼大多數編程語言對傳遞給函數的參數使用急切的評估?

對我來說,似乎只有在函數使用它們,即懶惰地評估參數時,纔會更有意義。這對我來說更有意義,因爲它看起來會帶來性能上的好處:爲什麼要評估那些永遠不需要的東西?

而且,假設你想實現一個if函數接受一個布爾值,以及對象返回如果布爾是真實的,而另一個對象返回如果布爾是假的:

object if(bool condition, object valueIfTrue, object valueIfFalse) { 
    if(condition) return valueIfTrue; 
    return valueIfFalse; 
} 

在即使函數總是隻需要其中的一個,也總是對兩個對象進行評估,這最多會導致輕微的不必要開銷,並且最壞的情況下會導致無限循環。這就是說,由於大多數編程語言都使用了對函數參數的急切評估,所以我認爲它通常是以這種方式進行的。在這裏,我忽略了一些急切的評價是否有很大的好處,僅僅是因爲以這種方式實現語言比較容易,是傳統還是什麼?

+0

因爲在這些非惰性語言中編譯/解釋代碼很容易。 – 2012-01-10 04:21:25

回答

5

有幾個原因,我已經看到了渴望評價,這兩者都是重要的:

  1. 急於評價意味着副作用立即總是發生。如果你使用懶惰評估,你不能依靠你以前做過的事情的副作用已經生效。懶惰的評估帶來了一定量的內存膨脹。通常,存儲計算結果的內存通常比存儲描述計算的thunk的內存少得多。這可能會導致使用太多的內存(即時間與內存的權衡),有時更重要的是,更難以計算出程序/算法的內存特性。

懶惰評估可以是一個強大的工具,但它不是沒有成本。純函數式語言傾向於避免#1問題,因爲它們沒有副作用(一般情況下),但有時仍被問題#2咬住。允許延遲評估的語言(LISP宏是這種形式的一種形式,儘管與懶惰評估不一樣)可以兼顧兩者的優點,但是以編程人員更多努力爲代價。

3

選項1 - 所有arguements加載到寄存器,通話功能

選擇2 - 加載的第一個參數,評估是否有必要,等待CPU管道疏通,弄一個參數,評估是否有必要....然後將所需的參數加載到寄存器中,使用額外的邏輯執行功能以標記哪些寄存器正在使用。

一個「如果」已經將導致性能滯留無論如何,你需要等待,看看您正在執行其代碼路徑(由分支預測略微保存)

3

爲了讓懶惰的評價工作,需要有額外的代碼和數據以跟蹤表達式是否已被評估。在某些情況下,這會比急切的評估花費更多。確定一個表達式是否可以從懶惰評估中受益可能需要非常高層次的程序工作知識;編譯器和/或解釋器當然不會有這種知識。另外,如果函數或表達式具有副作用,那麼懶惰的評估策略可能會使程序的行爲方式違反直覺,難以調試。這在函數式編程語言中當然不是問題,因爲在設計中沒有副作用。實際上,懶惰評估是大多數(如果不是全部的話)函數式編程語言的默認策略。

這就是說,沒有什麼能夠阻止你在不同的地方使用這兩種策略。如果在非平凡程序中使用混合方法,我不會感到驚訝。

2

除了已經提供的優秀答案,懶惰評估還有另一個實際問題。如果您在最後一個「使用」時只有懶惰地評估了一系列表達式,則可能很難識別性能瓶頸。

+0

你能舉個例子嗎?我試圖想象你正在談論的那種代碼。 – 2012-01-10 04:03:14

+0

好吧,假設你有一個參數'x'給一個函數,當它被賦值時,它自己得到另一個變量'y'的值,並且這種鏈返回。可能有一些評估緩慢,哪些是瓶頸,但是當你評估'x'時你會看到它們。這可能會產生誤導,並且起源有時難以追查。 – 2012-01-10 04:13:56

0

回到白堊紀時期,有很多語言都是這樣做的。例如,SNOBOL。 ALGOL 68有一個「按名稱呼叫」的功能,它做了這樣的事情。 C(以及它的許多衍生物)在一個非常具體的情況下完成它,它被描述爲一個布爾表達式的「短路」。總的來說,它幾乎總是造成更多混亂和錯誤的原因,而不是實現權力的源泉。

+0

我不認爲Algol的名字叫做懶惰評估,我認爲這是通過引用而不是值。 – 2012-01-12 01:09:44

+0

ALGOL的名稱更多是一個文本替換,明確不是一個參考,所以我認爲它可以作爲懶惰評估。雖然現在我想到了它,但可能是ALGOL 60引入了它,而不是ALGOL 68. – 2012-01-12 17:24:21

+1

啊...... 20世紀60年代,「[白堊紀時期](http://stackoverflow.com/questions/1463321/was -algol-ever-used-for-mainstream-programming)「當我們是巨人並在月球上行走時::-) Algol60已經打了電話。 Algol68沒有按名稱呼叫,但是68通過引用呼叫。而且,......編程人員可以通過使用「程序」來在程序中實現懶惰評估,c.f. [使用程序進行短路評估](http://stackoverflow.com/questions/9462051/short-circuit-evaluation-using-procedures) – NevilleDNZ 2012-04-02 00:48:27

相關問題