explicit renaming占い
- http://saito.hatenablog.jp/entry/2014/11/18/233209
- explicit renaming でスコープを曲げる
ここで定義されているlet/scopeマクロは、"定義位置に引数をbeginで囲って展開する"という動作をしている。
これが期待通り動作しないのはマクロの合成問題( http://d.hatena.ne.jp/mjt/20141011/p1 )と言える。便宜上このように番号を振ると:
(let ((x 1)) ;; ← ★ x:1 (let/scope scope-1 ;; ← ★ scope-1:1 (let ((x 2)) ;; ← ★ x:2 (let/scope scope-2 (let ((x 3)) ;; ← ★ x:3 (let/scope scope-1 ;; ← ★ scope-1:3 (let ((x 4)) ;; ← ★ x:4 (display (scope-2 (scope-1 x))) (display (scope-2 x)) (display (scope-1 x)) (display x))))))))
displayの並びは
(display (scope-2 (scope-1:1 x:2)) (display (scope-2 x:2)) (display (scope-1:3 x:3)) (display x:4)
のようになることが期待される(おそらくGaucheの動作は何か間違っている)。
つまり、"(display (scope-2 (scope-1 x)))"のscope-2を展開するときにscope-1だけではなくxもx:2にリネームされてしまうため、仮にscope-1の位置に挿入したとしても、直上のx:1にはマッチしない。
... 次の問題は、期待通りの動作をするlet/scopeをer-macroで(補助マクロを導入することなく)実現できるかというポイントになるが、今のところ良い方法が思いあたらない。
chibi-schemeの場合はidentifier→symbolを提供しているので、R6RSのsyntax→datumのように一旦文脈情報を取り去った上でrenameする手が有る。
(define (traverse0 proc obj) ;; traverse0に改名しておく。また、chibi-schemeにはidentifier?が有るので適合するようにid?を変えておく。 (let loop ((obj obj)) (cond ((id? obj) (proc obj)) ((pair? obj) (cons (loop (car obj)) (loop (cdr obj)))) ((vector? obj) (vector-map loop obj)) (else obj)))) (define (strip sexp) (traverse0 identifier->symbol sexp)) (define (traverse proc obj) (traverse0 proc (strip obj)))
つまり、他の処理系では他の対策が必要になることになる。
R7RS largeではer-macroを標準にすることを意図していると思うけど、この辺を統一しておかないとあまり役に立たない気がする。そもそも、単純にシンボルを連結するようなマクロでもポータブルに書けないのは困るので、何か見落しているのかもしれない。(このidentifier?問題のために、nmoshでは移植性ライブラリであるyuniに専用のシンボル連結構文を入れている( http://d.hatena.ne.jp/mjt/20140914/p1 )。)