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

末尾再帰かどうかは、結果を返すために呼んでいるのが自分かどうか。言い換えれば、(今回のケースでは)+を実行するときに結果が揃っているか否か。