Scheme の話題がネタ切れ気味になってきたので、過去に書いたものを見返していたところ、 R6RS で explicit renaming を実装するというネタが目に止まった。
主題の無い日記: explicit-renamingそういえば syntactic closure もいずれやってみようと思っていたのだった。
で、出来上がったのがこちら。
#!r6rs
(library (syntactic-closure)
(export sc-macro-transformer make-syntactic-closure)
(import (rnrs))
(define (tree-walk proc ls)
(let loop ((ls ls))
(cond ((null? ls) '())
((pair? ls) (cons (loop (car ls)) (loop (cdr ls))))
(else (proc ls)))))
(define-syntax sc-macro-transformer
(lambda(stx2)
(syntax-case stx2 ()
((k proc)
#'(lambda(stx)
(syntax-case stx ()
((env . arg)
(tree-walk
(lambda(x) (if (symbol? x) (datum->syntax #'k x) x))
(proc (syntax->datum #'(env . arg)) #'env)))))))))
(define (make-syntactic-closure env names form)
(tree-walk
(lambda(x)
(if (symbol? x)
(if (memv x names) x (datum->syntax env x))
x))
form))
)
使用例はこんな感じ。
#!r6rs
(import (rnrs)
(for (syntactic-closure) expand))
(define-syntax swap!
(sc-macro-transformer
(lambda (form env)
(let ((a (make-syntactic-closure env '() (cadr form)))
(b (make-syntactic-closure env '() (caddr form))))
`(let ((value ,a))
(set! ,a ,b)
(set! ,b value))))))
(define c 1)
(define d 2)
(swap! c d)
(display c) (newline)
(display d) (newline)
いくつかの処理系で試していたのだが、 Ypsilon でだけ以下のような例がエラーになってしまった。 let-syntax の定義部での文脈をうまく扱えないらしい。
#!r6rs
(import (rnrs)
(for (syntactic-closure) expand))
(let-syntax ((foo (sc-macro-transformer
(lambda(expr env)
(let ((var (cadr expr)))
`(display ,(make-syntactic-closure env '() var)))))))
(let ((x 2))
(foo x)))
Document ID: f4f2d89748919445e1bcb89d09350dd8
0 件のコメント:
コメントを投稿