遅延評価は, 式の値が実際に必要になるまで, 式の評価 (実際の値を求めるの計算) を 後回しにする技術である.
lazy_eval.d
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import std.stdio;
void dotimes(uint count, lazy void dg){
/*
引数に lazy を使うとその引数は遅延評価されるようになる
writeln("hello") の評価を dg() の呼び出しまで遅らせている
*/
for(uint i = 0; i < count; i++){
dg();
// dg; // この使い方も OK
}
}
void main(){
dotimes( 5, writeln("hello") );
}
|
lazy_eval.d の実行結果は:
[cactus:~/code_d/d_tuts]% ./lazy_eval
hello
hello
hello
hello
hello
lazy_eval2.d
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import std.stdio;
import std.perf;
// 普通の関数
void normal(string s, int i){
if (i % 1000000 == 0)
write(s);
}
// 引数を遅延評価する関数
void lazyEval(lazy string s, int i){
if(i % 1000000 == 0)
write(s);
}
// 実際に必要になるまで遅延評価される関数
string text(){
char[] ret;
for(int i = 0; i < 10; i++)
ret ~= "A";
ret.length = 0;
return ret.idup;
}
void main(){
auto t1 = new std.perf.PerformanceCounter;
auto t2 = new std.perf.PerformanceCounter;
// 普通の関数
t1.start();
for(int i = 0; i < 50000000; i++)
normal(text(), i);
t1.stop();
writeln("normal: ", t1.milliseconds, "[ms]");
// 引数を遅延評価する関数
t2.start();
for(int i = 0; i < 50000000; i++)
lazyEval(text(), i);
t2.stop();
writeln("lazy: ", t2.milliseconds, "[ms]");
}
|
lazy_eval2.d の実行結果は:
[cactus:~/code_d/d_tuts]% ./lazy_eval2
normal: 67344[ms]
lazy: 356[ms]
tak_norm_lazy.d
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import std.stdio;
import std.perf;
// 普通の竹内関数
int normTak(int x, int y, int z){
if(x <= y)
return y;
else
return normTak( normTak(x-1, y, z), normTak(y-1, z, x), normTak(z-1, x, y) );
}
// 引数を遅延評価する竹内関数
int lazyTak(lazy int x, lazy int y, lazy int z){
if(x <= y)
return y;
else
return lazyTak( lazyTak(x-1, y, z), lazyTak(y-1, z, x), lazyTak(z-1, x, y) );
}
void main(){
auto t1 = new std.perf.PerformanceCounter;
auto t2 = new std.perf.PerformanceCounter;
// 普通の竹内関数
t1.start();
writeln( normTak(15, 10, 0) );
t1.stop();
writeln("Normal Tak Function: ", t1.milliseconds, "[ms]");
// 引数を遅延評価する竹内関数
t2.start();
writeln( lazyTak(200, 50, 20) );
t2.stop();
writeln("Lazy Tak Function: ", t2.milliseconds, "[ms]");
}
|
tak_norm_lazy.d の実行結果は:
[cactus:~/code_d/d_tuts]% ./tak_norm_lazy
15
Normal Tak Function: 48374[ms]
200
Lazy Tak Function: 39[ms]