Macros 在Racket中使用语法参数

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)体)

(定义语法参数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