遅延評価

誰かが、遅延評価が嬉しいと思ったことはないと書いていたような気がしたが、そんなこともないのではないかと思って、実験してみることにした。
遅延評価を上手く使うと、時間のかかる計算を、結果の再利用をしてリソースの節約をするようなコードが簡単に書けるはず。

サンプル

module sine

import StdEnv

Start
	= doCalc 0.0 1
where
	// 計算の再利用のために必要な追加コード //
	calcs = getCalc
	where
		getCalc
			= [calc x \\ x <- [0..]]
	// ==================================== //

	doCalc :: !Real Int -> Real
	doCalc res 9999999
		= res
	doCalc res x
		= doCalc (res + (calcs!!i)) (x+1)
		//= doCalc (res + (calc i)) (x+1)
	where
		i = abs (((~3*x*x+16*x+350) rem 4) * 23)

calc x
	= (sinh o tan o sin o cos o acos o atan o cosh o asin) ((toReal x) / 1000.0)

calcという計算を、9999999回繰り返して、その合計を求めるという計算。
で、コメントアウトした方が、計算の再利用をしていないコード。
再利用をするために必要なコードは、わずか4行。

実行時間

再利用した場合

$ time ./sine.exe 
9633764.15158449

real    0m7.851s
user    0m0.020s
sys     0m0.040s

再利用しない場合

$ time ./sine.exe 
9633764.15158449

real    0m33.162s
user    0m0.010s
sys     0m0.060s

まあ、この結果はあたりまえですけど、再利用をする側は、もっと速いと思っていたんだけど。