检查标识符是否在宏扩展点上词汇结合



这可能是一个新手问题,但是我试图编写一个宏来检测标识符是否在宏扩展点上词汇绑定,并相应地更改其输出。这是否可以在R6RS方案中进行,如果是的话,如何?

为什么我想知道

我正在使用宏(Macros)在Chez方案中编写一个玩具Objective-C结合层,而我的最初挑战是有效地处理Objective-C选择器。该程序必须在运行时查询Objective-C运行时,以了解与每个选择器名称相对应的实际SEL对象。该程序中使用的选择器名称将在静态上以静态为单位,并且在扩展过程中很容易,很容易将我的宏插入该查询代码,但是我想避免对相同的选择器名称重复查询。

我对此的第一个想法是为与 SEL外来对象绑定的方案定义有一些命名约定。这样,我可以为每个唯一的选择器提供一个(define),因此每个选择器都有一个运行时查询。这取决于我的宏能够检测到任何给定选择器的这些绑定,并在它们尚不存在的情况下介绍它们,因此我的问题。

此解决方案仍然不完美,因为我的宏可能会在内部范围内扩展,但这对我来说是最明显的。是否有更好的方法在扩展时"实习"表达式?

我不完全确定是否可以通过指定的行为来实现这一点,但是您可以像以下内容一样做:

#!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=?检查给定标识符是否绑定。make-binding-check宏可采用2个标识符,当宏扩展时,它们都应该取消结合。为了制作这样的未结合标识符,该代码由2个部分,实现和环境组成:第一个是(bound helper),它提供了标识符比较的实现。另一个是(bound),几乎没有绑定环境。

比较是与要检查的环境库和实际标识符传递的标识符进行的。如果实际标识符绑定到任何事物,那么它将与未结合标识符相同,因此bound?应返回#f。(如果定义make-binding-check并检查,则它将返回#T,因为它在(bound)库中定义。)

谨慎这可能会根据您正在使用的实施而起作用,也可能不起作用,我不确定这对Chez是否有效。

最新更新