バックトラックポイントの生成をマクロ化してみた
さっきの文章を書いていて、この用途で使うcall/ccを汎用化できそうな気がしてみたので、ちょっとマクロ化してみた。
let1とlet/cc使ってるのでgauche用だが、そこを展開すれば他のschemeでも使えると思う。
(define-syntax backtrack-point/values (syntax-rules () ((_ . initial-values) (let1 backtrack-point #f (receive backtrack-values (let/cc cont ;; このset!はletrec用途なので副作用無し (set! backtrack-point cont) (values . initial-values)) (apply values backtrack-point backtrack-values))))))
以下のように使える。
(receive (backtracker n m) (backtrack-point/values 0 20) (print n) (when (< n m) (backtracker (+ 1 n) m)) ; receiveのところまで戻る (print "done."))
そして、作ってみて、何かに似てると思ったら、named-letに似てる事に気付いた。
named-let書式のマクロも作ってみようと思ったが、syntax-rulesを書くのが面倒そうだったのでやめた。