ifマクロ
Gaucheでifマクロを書いてみた。
マクロ名は if だとアレなので %if とする。
当然ながら if case cond といった分岐用特殊形式の使用は禁止。
else無指定への対応すると煩雑になるので2つに分けています。
(define-macro (%__if test then else) `((assoc-ref `((#t . ,(^() ,then)) (#f . ,(^() ,else))) (boolean ,test)))) (define-macro (%if test then . else) `($ %__if ,test ,then ,($ %__if (null? else) (undefined) (car else))))
thenとelseの式をサンクにするので名前付letの再帰は上手くいかないかな、と思いましたが大丈夫でした。
(let loop ((n 10) (acc 1)) (%if (zero? n) acc (loop (- n 1) (* acc n)))) ;; ループ呼び出しがサンクになってる。 ;;=> 3628800
ちなみにClojureで同様にしてrecurをサンクにすると上手くいきませんでした。recurのジャンプ先がloopではなくサンクを作っている fn になってしまうからですね。