exportされた変数の制約

R6RS では import した変数に set! することは出来ない。 明示的な import であろうと暗黙の import であろうと関係なく set! できない。

そこをなんとか set! できる (かの) ようにするマクロを書こうとしたのが前回の記事だ。

http://saito.hatenablog.jp/entry/2012/09/08/091259

どうしてエラーになるのかわからずにおり、健全マクロのリネームが関係していると予想していたのだが、コメントで指摘をもらって確認したところ、 import した変数に set! できないだけでなく export した変数にも set! できないという制約の存在があることがわかった。

こういった構文違反の場合には &syntax コンディション型の例外を発生させることになっている (R6RS 5.5 Syntax violations) ので、実行できてしまった Racket と Ypsilon の挙動が R6RS 的には違反ということになるのだろう。

とりあえずこの挙動を踏まえて、 define-settable を書き直してみた。

#!r6rs
(library (settable-variable)
  (export define-settable)
  (import (rnrs))
  
  (define-syntax define-settable
    (syntax-rules ()
      ((_ var val)
       (begin
         (define dummy val)
         (define (set-dummy! x) (set! dummy x))
         (define (dummy-ref) dummy)
         (define-syntax var
           (make-variable-transformer
            (lambda(x)
              (syntax-case x (set!)
                ((set! _ a) #'(set-dummy! a))
                (_ #'(dummy-ref))))))))))
  )

Document ID: 343406d8aa951219f764a3e7ab850083