【问题标题】:Using Syntax Parameters in Racket在 Racket 中使用语法参数
【发布时间】:2013-09-19 16:47:29
【问题描述】:

为了简洁起见,我正在尝试定义一个生成匿名函数的宏,该函数采用一个名为它的参数,而不是

(λ (it) body)
我可以写
(λλ body)

(换句话说,(λλ body) 转换为 (λ (it) body)

(define-syntax-parameter it #f)
(define-syntax λλ
  (syntax-rules ()
    ((_ body)
     (λ (x) (syntax-parameterize ((it x)) body)))))
(λλ (< it 0)) ; For testing

我在(define-syntax-parameter if #f) 得到operators.rkt:13:28: ?: literal data is not allowed; no #%datum syntax transformer is bound in the transformer environment in: #f,但据我所知,这与球拍文档中关于如何使用define-syntax-parameter 的示例完全相同。我可以通过用函数替换#f 来抑制错误(我使用了member,但不是出于任何真正的原因),但在这样做之后,我得到operators.rkt:17:38: x: identifier used out of context in: x。我做错了什么?

【问题讨论】:

    标签: macros racket


    【解决方案1】:

    您在example 中遗漏了syntax-id-rules 部分。它是指定it 应该扩展为x 的部分。或者,您可以使用make-rename-transformer

    #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
    

    【讨论】:

    • 为了进一步澄清这一点,语法参数“绑定”的东西存在于语法世界中——所以你不想使用x,因为这是一个运行时的东西,而是你想使用#'x。但是您确实想创建一种扩展#'x的宏,因此需要syntax-id-rules或更方便的make-rename-transformer速记。
    【解决方案2】:

    语法参数并不是实现您心目中的宏的唯一方法。一种更简单(IMO)的方法是只使用datum-&gt;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
    

    【讨论】:

    • 其实我相信这是syntax-parameterize的一个很好的用法。请参阅 Barzilay 等人的“保持清洁”论文。
    • 公平地说,我会稍微软化我的措辞。我仍然认为datum-&gt;syntax 会这样做有点矫枉过正,但你的回答很好(+1)。
    • 我认为关键是您可以在syntax-rules 中保持不卫生,而不必切换到较重的syntax-case
    • @stchang 这实际上是一个很好的观点,我会记住,下次我开始告诉人们“不,你不能在syntax-rules 中破坏卫生”。 :-P
    • 。 ...对不起,但是作为一个投入大量精力来解释为什么这是一个坏主意的人,看起来我在道德上有义务在这个问题上对你投反对票(这是第一次......)。 datum-&gt;syntax 的主要真正(和高级)问题是它看起来有效,只是它以后会可怕地咬你。它特别有效地解决了足以让人们回到“defmacro 的简单世界”的错误。
    猜你喜欢
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    相关资源
    最近更新 更多