R6RS において、識別子が既に束縛されているかどうかを判定することを考えていた。 つまりコードで表すと以下のような bound? と if-bound をどう定義するかということだ。
#!r6rs (import (rnrs) (bound)) (display (bound? sin)) (display (bound? lambda)) (display (bound? syntax)) (display (bound? hoge)) (newline) ;; この定義の有無で以降の場合分け処理が分岐する ;; (define hige "This is hige.\n") (if-bound hige (display "hige was bound.\n") (begin (display "hige was not bound.\n") (define hige "This is alternate hige.\n"))) (display hige)
このプログラムは
#t#t#t#f hige was not bound. This is alternate hige.
という結果を表示する。
コメントアウトしている部分を有効にすると
#t#t#t#f hige was bound. This is hige.
となる。
私はこのような実装を考えた。
#!r6rs (library (bound helper) (export make-definition) (import (rnrs)) (define-syntax make-definition (lambda(stx2) (syntax-case stx2 () ((_ if-bound bound?) #'(begin (define-syntax if-bound (lambda(stx) (syntax-case stx () ((_ id consequent) #'(if-bound id consequent (begin))) ((_ id consequent alternate) (not (free-identifier=? (datum->syntax #'if-bound (syntax->datum #'id)) #'id)) #'consequent) ((_ id consequent alternate) #'alternate)))) (define-syntax bound? (syntax-rules () ((_ id) (if-bound id #t #f))))))))) )
#!r6rs (library (bound) (export bound? if-bound) (import (bound helper)) (make-definition if-bound bound?) )
マクロ定義時の文脈で識別子を解釈するとそれは未束縛なので、未束縛な識別子と比較して一致すればそれは未束縛であると判断できる。 間に一個ライブラリを狭んでいるのは何も定義されていない環境を作るためだ。
確認のために上述のコードを与えてみたところ以下の処理系では期待通りに動いた。
- Racket
- mosh
- IronScheme
- Petite Chez Scheme
以下の処理系では期待とは異なる判定結果が示される。
- Ypsilon
但し、 Ypsilon では if-bound の方はちゃんと判定できているらしいのに、 bound? の方が期待とは異なる結果を返すのがよくわからない。
それから、以下はエラーを返す。
- nmosh
- Larceny
どうやら、 hige が定義されていない場合に hige を定義するというのが矛盾と見做されるっぽい。 なるほど、そういう解釈もできるのかと目から鱗。
Document ID: 0c5eb1e95133ee6614c948f2930e2c2b