マクロでtarai回し 3回目
zを評価するタイミングはもっと遅らせられることに気付いたので、元にする関数をちょっと修正した。
(define (tarai-r/o x y z) (let ((x-value (force x)) (y-value (force y))) (if (<= x-value y-value) y-value (tarai-r/o (delay (tarai-r/o (1- x-value) y-value z)) (delay (tarai-r/o (1- y-value) z x-value)) (delay (let ((z-value (force z))) (tarai-r/o (1- z-value) x-value y-value)))))))
そうすると、マクロ版はこうなった。
(define-syntax tarai-r/o (syntax-rules () ((_ 0 %x %y %z %k ...) (tarai-r/o "force" %x (tarai-r/o 1 %y %z) %k ...)) ((_ 1 %y %z %x-value %k ...) (tarai-r/o "force" %y (tarai-r/o 2 %z %x-value) %k ...)) ((_ 2 %z %x-value %y-value %k ...) (tarai-r/o "loop" %x-value %y-value %x-value %y-value %z %k ...)) ((_ "loop" (%x1 %x2 ...) (%y1 %y2 ...) %x-value %y-value %z %k ...) (tarai-r/o "loop" (%x2 ...) (%y2 ...) %x-value %y-value %z %k ...)) ((_ "loop" () (%y1 ...) %x-value %y-value %z %k ...) (tarai-r/o "return" %y-value %k ...)) ((_ "loop" (%x1 %x2 ...) () %x-value %y-value %z %k ...) (tarai-r/o 0 ("delay" (tarai-r/o 3 %x-value %y-value %z %k ...)) ("delay" (tarai-r/o 4 %x-value %y-value %z %k ...)) ("delay" (tarai-r/o 5 %x-value %y-value %z %k ...)))) ((_ 3 (%x1 %x2 ...) %y-value %z %k ...) (tarai-r/o 0 (%x2 ...) %y-value %z %k ...)) ((_ 4 %x-value (%y1 %y2 ...) %z %k ...) (tarai-r/o 0 (%y2 ...) %z %x-value %k ...)) ((_ 5 %x-value %y-value %z %k ...) (tarai-r/o "force" %z (tarai-r/o 6 %x-value %y-value) %k ...)) ((_ 6 %x-value %y-value (%z1 %z2 ...) %k ...) (tarai-r/o 0 (%z2 ...) %x-value %y-value %k ...)) ((_ "force" ("delay" (%f ...)) %k ...) (%f ... %k ...)) ((_ "force" %val %k ...) (tarai-r/o "return" %val %k ...)) ((_ "return" %val) %val) ((_ "return" %val (%k1 ...) %k2 ...) (%k1 ... %val %k2 ...)) ))
forceに当たる部分も本来の動作(promiseだったら本体を評価して、そうでなければ何もしない)に合わせたので、少し記述がシンプルになった。