マクロで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だったら本体を評価して、そうでなければ何もしない)に合わせたので、少し記述がシンプルになった。