【发布时间】:2016-09-05 02:55:53
【问题描述】:
我正在尝试编写一个行为类似于球拍定义的宏,但以某种方式处理完全扩展的球拍程序(为简单起见在下面的示例中进行了扩展):
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(let* ([define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
[fully-expanded (local-expand define/racket 'top-level (list))])
fully-expanded)]
[(_ id expr) (syntax/loc stx (define id expr))]))
除非满足递归定义,否则一切正常:
(define/expand (sum n)
(if (<= n 0)
0
(+ n (sum (- n 1)))))
运行它会引发错误
sum:模块中的未绑定标识符:sum
指向sum 的调用(不是定义)。显然sum 的定义没有被本地扩展器捕获。我尝试了一种直接的修复方法:创建新的本地定义上下文并将 head 绑定到其中:
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(let* ([ctx (syntax-local-make-definition-context)] ; <- These two lines added
[_ (syntax-local-bind-syntaxes (list #'head) #f ctx)] ; <--/
[define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
[fully-expanded (local-expand define/racket 'top-level (list) ctx)])
fully-expanded)]
[(_ id expr) (syntax/loc stx (define id expr))]))
它解决了问题(本地扩展成功将程序扩展为define-values),但创建了另一个:
模块:在:sum 中定义的上下文标识符
指向sum的定义。原因可能是扩展器将标识符绑定到 ctx 中的一个,而不是当前上下文中的 head。
直觉上这似乎不是一个罕见的问题,但我无法通过网络找到解决方案。我认为我应该以某种方式使用local-expand/capture-lifts 和syntax-local-lift-expression,但我不知道如何正确使用它。有人可以澄清发生了什么和/或提示如何解决它吗?
【问题讨论】:
-
另一个有时有用的技巧:在绑定未绑定变量的 lambda 上调用
local-expand,然后对结果进行模式匹配以获取正文。