Schemeの課題をあの実装で の2
64bit環境だとHeap/Stackがoverflowしねぇということで、最近話題のypsilonを試すことに。
traceとか面白いので細かいツールとして使っていこうかな。。(素直にGauche使えよというのは置いておくとして)
インストールはWebサイトの記述に従う。現時点でconfigure等のAutotools対応は無く、
make PREFIX=/opt/ypsilon -j3 make PREFIX=/opt/ypsilon install
のようにすればすぐにインストールできる。個人的には、いわゆるcvsビルドは/optに纏めて追跡しているのでこのようにしている。
あとは素直に。
$ cd /opt/ypsilon/bin $ ./ypsilon --heap-limit=16 Ypsilon 0.9.6-update2 Copyright (c) 2008 Y.Fujita, LittleWing Company Limited. > (define (sum x)(if (= x 1) 1 (+ x (sum (- x 1))))) > (sum 1) 1 > (sum 10) 55 > (sum 999999) fatal: heap memory overflow (16MB) [exit]
標準ライブラリ以外の依存は無いので、ライブラリパス等を通さずに直接実行できる。
$ ./ypsilon --heap-limit=16 Ypsilon 0.9.6-update2 Copyright (c) 2008 Y.Fujita, LittleWing Company Limited. > (define (sum2 x y)(if (= y x) x (+ y (sum2 x (- y 1))))) > (sum2 1 1) 1 > (sum2 1 10) 55 > (sum2 10 20) 165 > (define (sum3 x) (sum2 1 x)) > (sum3 1) 1 > (sum3 10) 55 > (sum3 999999) fatal: heap memory overflow (16MB) [exit]
最後は末尾再帰か。
単純に、
for(count=0;count<=end;count++){ cur += count; }
と考えると、forの中一行がループなので必要な変数とともに独立させて、
$ ./ypsilon --heap-limit=16 Ypsilon 0.9.6-update2 Copyright (c) 2008 Y.Fujita, LittleWing Company Limited. > (define (sum4-itr count end cur) (if (<= count end) (sum4-itr (+ count 1) end (+ cur count)) cur)) > (define (sum4 x) (sum4-itr 0 x 0)) > (sum4 1) 1 > (sum4 10) 55 > (sum4 999999) 499999500000 > (sum4 9999999) 49999995000000 > (sum4 99999999) 4999999950000000
末尾再帰かどうかは、結果を返すために呼んでいるのが自分かどうか。言い換えれば、(今回のケースでは)+を実行するときに結果が揃っているか否か。