Re: [心得] lazy evaluation

看板PLT (程式語言與理論)作者 (noctem)時間17年前 (2007/03/05 14:14), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串2/3 (看更多)
※ 引述《godfat (godfat 真常)》之銘言: : 推 ephesians:lazy是用來節省計算成本,結果仍浪費成本啊! XD 03/02 06:45 : 能越早做 eval 或 binding 執行效率當然會越高,我覺得大部份的情況下 : 還是需要 eager eval, 只有很少數是真的需要用 lazy eval. 當然,這是 : 指使用 imperative 之形式的話,funational 又是另一回事了 @@ 我記得有研究分析過真正使用 non-strictness(*) 的時機到底有 多少,結論是不多,所以不值得(像 Haskell 這樣)把它當作 default. 不過我可能記錯。 (*) 嚴格說起來,lazy evaluation 只是一種實作 non-strict 語意的方法之一(還有其他的方法)。不過 lazy evaluation 這個詞念起來比較 印象深刻,所以實際上常常混用。 我之前不知道 D 這個語言。看前一篇的描述,似乎就頗像是把 eager 當作 default, 需要 lazy 的時候再特別宣告一下。 對我來說,我是已經很習慣 laziness 了,並不知道自己真的是否 有用到,只覺得如果沒有會怪怪的。 * * * 關於 log 的例子指出了重要的一點: non-strictness 提供了另一種 模組化的可能。像 log 如果不是 non-strict 的,就沒法獨立出來變 成一個可重用的函數。 「Lazy evaluation 省計算」這件事情其實是個誤解/誤導。舉個例子, 如果要算 n 階層,我們可以先產生 [1,2,3...,n] 的串列,然後把它 乘起來;要產生 [1,2,3..n] 這個串列,可以先產生一個從 1 開始 的無限長串列(寫成 [1..] )然後取前面 n 個。所以可以這麼做: foldr (*) 1 (take n [1..]) 其中 take n 取串列的前面 n 個元素, foldr (*) 1 把他們 乘起來。可是先產生一個長串列、再截一段出來、再乘起來,不是很 費工又耗記憶體嗎?我們說,沒關係,在 lazy evaluation 之下, 只有使用到的地方才會去計算,所以其實這個程式用的是 constant space, 而且也沒有真的去產生無限長的串列。 所以 lazy evaluation 省時間/空間?其實沒有這回事,因為所謂 省是要看和誰比。如果今天是用一個 eager 的語言,程式根本就 不會這樣寫。Lazy evaluation 「省」出來的結果,其實和一個 eager 程式本來會寫成的樣子是一樣的。而且 laziness 還會有些 overhead. 那 laziness (或 non-strictness) 的好處是什麼?其一是這些 take, foldr, map 等等函數都是可以在很多場合下重複使用的元件。 Non-strictness 增加了模組化的可能。其二是我們能表達「無限長 的串列」這種東西。 論效率的話,目前的 lazy 語言還是比較難實作得有效率。有人 提出一種所謂的「lenient evaluation」,認為是 lazy 與 eager 之間折衷的好方法。不過是否真如此就還需要研究了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.109.20.217

03/06 23:51, , 1F
請問為何能夠有 "增加模組化的可能" ?
03/06 23:51, 1F
文章代碼(AID): #15wxLGuc (PLT)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 3 篇):
文章代碼(AID): #15wxLGuc (PLT)