Macros 在Racket中使用语法参数
为了简洁起见,我试图定义一个宏来生成一个匿名函数,该函数使用一个名为it的参数,因此Macros 在Racket中使用语法参数,macros,racket,Macros,Racket,为了简洁起见,我试图定义一个宏来生成一个匿名函数,该函数使用一个名为it的参数,因此 (λ(it)体) 我会写 (λ体) (换句话说,(λλ体)转换为(λ(it)体)) (定义语法参数it#f) (定义语法λ) (语法规则() (uuu体) (λ(x)(语法参数化((it x))体 (λ(syntax插入标识符it: (define-syntax (λλ stx) (syntax-case stx () ((_ body ...) (with-syntax ((it (da
(λ(it)体)
我会写
(λ体)
(换句话说,(λλ体)
转换为(λ(it)体)
)
(定义语法参数it#f)
(定义语法λ)
(语法规则()
(uuu体)
(λ(x)(语法参数化((it x))体
(λ(<0));用于测试
我得到
运算符。rkt:13:28:?:不允许使用文字数据;没有#%datum syntax transformer绑定在transformer环境中:#f
at(如果#f)定义语法参数
,但据我所知,这与racket的文档中给出的如何使用定义语法参数的示例完全相同。我可以通过用函数替换#f
来抑制错误(我使用了成员,但不是出于任何真正的原因),但是在这样做之后,我得到了运算符。rkt:17:38:x:identifier在:x
中上下文之外使用。我做错了什么?语法参数并不是实现您想要的宏的唯一方法。一种更简单的(IMO)方法是只使用datum->syntax
插入标识符it
:
(define-syntax (λλ stx)
(syntax-case stx ()
((_ body ...)
(with-syntax ((it (datum->syntax stx 'it)))
#'(λ (it) body ...)))))
要使用您的示例:
(define my-negative? (λλ (< it 0)))
(my-negative? -1) ;; => #t
(定义我的负数?(λ(#T
您在中遗漏了语法id规则部分。它是指定It
应扩展到x
的部分。或者,您可以使用:
实际上,我相信这是语法参数化的一个很好的用法。见Barzilay等人的《保持清洁》一文。公平地说,我会稍微软化我的措辞。我仍然认为当datum->syntax
可以的时候,这是过分的,但是你的答案是好的(+1)。我认为关键是你可以在语法规则
中获得非卫生性,而不必切换到较重的语法案例
@stchange,这实际上是一个非常好的观点,下次我开始告诉人们之前,我会记住这一点“不,你不能违反语法规则”
“:-帕格…抱歉,但作为一个花了这么多精力解释为什么这是个坏主意的人,我似乎在道义上不得不在这一点上否决你(第一次…)。主要的真实(和高层)datum->syntax
的问题在于,它看起来很有效,只是以后会可怕地咬到你。它特别有效地防止了那些严重到让人们回到“defmacro
的简单世界”的bug。为了进一步澄清这一点,syntax参数“绑定到”的东西“生活在语法世界中——因此您不想使用x
,因为这是一个运行时的东西,而是想使用#'x
。但是您确实希望创建一种宏,它可以扩展到#x
,因此语法id规则
或更方便的make rename transformer
速记。
(define my-negative? (λλ (< it 0)))
(my-negative? -1) ;; => #t
#lang racket
(require racket/stxparam)
(define-syntax-parameter it #f)
(define-syntax λλ
(syntax-rules ()
((_ body)
(λ (x) (syntax-parameterize ([it (make-rename-transformer #'x)]) body)))))
((λλ (< it 0)) 5)
((λλ (< it 0)) -5)
#f
#t