schemeにおいて関数定義はこのようにする。
(define f (lambda(arg) ほにゃらら))
つまり、関数であるオブジェクトを変数に束縛するという考え方である。しかし、冗長であることから、大抵の処理系ではもっと簡単に定義できる構文が使える。その構文を利用すれば上の例と同じことをこのように書ける。
(define (f arg) ほにゃらら)
この記法は単なる便宜であり、意味的な差は無いとされている。
で、にちゃんねるのscheme関連スレで、letrecでもこのような記法を使えないかという話が出ていた。
(letrec ((c (lambda (a b) (+ a b))) (l (lambda (a b) (c a (c b 0))))) (l 1 2))
これが、
(letrecf (((c a b) (+ a b)) ((l a b) (c a (c b 0)))) (l 1 2))
こう書きたいというわけだ。
それに対して私はこのように回答した。
(define-syntax letrecf (syntax-rules () ((_ ((f b) ...) body ...) (let () (define f b) ... body ... ))))
で、今度はletに対してもこのようなバージョンを書いてみようと思って出来たのがこれ。
(define-syntax letf% (syntax-rules () ((_ (body ...) (r ...)) (let (r ...) body ...)) ((_ (body ...) (r ...) ((var args ...) fbody) next ...) (letf% (body ...) (r ... (var (lambda(args ...) fbody))) next ...)) ((_ (body ...) (r ...) (var obj) next ...) (letf% (body ...) (r ... (var obj)) next ...)) )) (define-syntax letf (syntax-rules () ((_ (a ...) body ...) (letf% (body ...) () a ...))))
なんか不格好。補助マクロが外から見えてしまう。R6RSにsyntax-caseとかいう構文を導入することが検討されているらしいけど、それがあればもっと綺麗に出来るだろうか。なんてschemeのせいにしてしまう私。
Document ID: 3670efb1dffc1cd6ab19982d57875c61