我不完全确定这是否可以通过明确指定的行为来实现,但你可以这样做:
#!r6rs
(library (bound helper)
(export make-binding-check)
(import (rnrs))
(define-syntax make-binding-check
(lambda (x)
(syntax-case x ()
((_ if bound?)
#'(begin
(define-syntax if
(lambda (xx)
(syntax-case xx ()
((_ b then els)
(free-identifier=? (datum->syntax #'if (syntax->datum #'b)) #'b)
#'els)
((_ b then els)
#'then))))
(define-syntax bound?
(lambda (xx)
(syntax-case xx ()
((_ b)
#'(if b #t #f))))))))))
)
(library (bound)
(export bound? if-bound)
(import (bound helper))
(make-binding-check if-bound bound?)
)
(import (rnrs) (bound))
(display (bound? foo)) ;; #f
(let ((foo 1))
(display (bound? foo))) ;; #t
(newline)
这个想法是free-identifier=?
用来检查给定的标识符是否被绑定。宏需要 2 个标识符,make-binding-check
当宏展开时,它们都应该是未绑定的。为了制作这样的未绑定标识符,代码由两部分组成,实现和环境:第一个是(bound helper)
提供标识符比较的实现。另一种是(bound)
几乎不提供绑定环境。
使用从环境库传递的标识符和您要检查的实际标识符进行比较。如果实际标识符绑定到任何东西,那么它将与未绑定标识符不同,因此bound?
应该 return #f
。(如果你定义make-binding-check
并检查,它会返回 #t 因为它是在(bound)
库中定义的。)
注意
这可能会也可能不会根据您使用的实现而起作用,我不确定这是否适用于 Chez。