バックトラックポイントの生成をマクロ化してみた

さっきの文章を書いていて、この用途で使う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を書くのが面倒そうだったのでやめた。