マクロでtarai回し 5回目
引数に0が含まれるときにも動くように修正した。
- tarai-mac.scm
#! /usr/bin/env gosh (define-syntax tarai (syntax-rules () ((_ (%x ...) (%y ...) (%z ...)) (tarai "loop" (%x ...) (%y ...) (%x ...) (%y ...) (%z ...))) ((_ "loop" (%x1 %x2 ...) (%y1 %y2 ...) %x-value %y-value %z %k ...) (tarai "loop" (%x2 ...) (%y2 ...) %x-value %y-value %z %k ...)) ((_ "loop" () (%y1 ...) %x-value %y-value %z %k ...) (tarai "return" %y-value %k ...)) ((_ "loop" (%x1 %x2 ...) () %x-value %y-value %z %k ...) (tarai 0 ("delay" (tarai 3 %x-value %y-value %z)) ("delay" (tarai 3 %y-value %z %x-value)) ("delay" (tarai 3 %z %x-value %y-value)) %k ...)) ((_ 0 %x %y %z %k ...) (tarai "force" %x (tarai 1 %y %z) %k ...)) ((_ 1 %y %z %x-value %k ...) (tarai "force" %y (tarai 2 %z %x-value) %k ...)) ((_ 2 %z %x-value %y-value %k ...) (tarai "loop" %x-value %y-value %x-value %y-value %z %k ...)) ((_ 3 %x %y %z %k ...) (tarai "force" %x (tarai 4 %y %z) %k ...)) ((_ 4 %y %z () %k ...) (tarai "force" %y %k ...)) ((_ 4 %y %z (%x1 %x2 ...) %k ...) (tarai 1 %y %z (%x2 ...) %k ...)) ((_ "force" ("delay" (%f ...)) %k ...) (%f ... %k ...)) ((_ "force" %val %k ...) (tarai "return" %val %k ...)) ((_ "return" %val) %val) ((_ "return" %val (%k1 ...) %k2 ...) (%k1 ... %val %k2 ...)) )) (define (main args) (display (macroexpand '(tarai (12 11 10 9 8 7 6 5 4 3 2 1) (6 5 4 3 2 1) ()))) (newline))
% time ./tarai-mac.scm (12 11 10 9 8 7 6 5 4 3 2 1) real 0m0.038s user 0m0.025s sys 0m0.001s
ちなみに、実行時間の比較をすると、
- tarai.scm
#! /usr/bin/env gosh (define (tarai x y z) (if (<= x y) y (tarai (tarai (- x 1) y z) (tarai (- y 1) z x) (tarai (- z 1) x y)))) (define (main args) (display (tarai 12 6 0)) (newline))
% time ./tarai.scm 12 real 0m2.537s user 0m2.458s sys 0m0.006s
- tarai-delay.scm
#! /usr/bin/env gosh (define (tarai x y z) (if (<= (force x) (force y)) (force y) (tarai (delay (tarai (- (force x) 1) y z)) (delay (tarai (- (force y) 1) z x)) (delay (tarai (- (force z) 1) x y))))) (define (main args) (display (tarai 12 6 0)) (newline))
% time ./tarai-delay.scm 12 real 0m0.028s user 0m0.012s sys 0m0.006s
さすがにpromiseを使ったものよりは落ちるが、マクロ版も意外と効率は良いようだ。