Macros 关于球拍宏的两个问题

Macros 关于球拍宏的两个问题,macros,scheme,racket,Macros,Scheme,Racket,关于卫生宏观 我不完全理解宏是如何工作的。这里有两个例子。 第一个是: 这个很好,但是这个: #lang racket (define-syntax (g stx) (syntax-case stx () ([_ arg] #'(display arg)))) (define display 1) (g 3) 将引发异常。如何解释这两种情况之间的区别 如何定义这样的宏 我想定义一个宏来允许racket中的匿名递

关于卫生宏观

我不完全理解宏是如何工作的。这里有两个例子。
第一个是:

这个很好,但是这个:


    #lang racket
    (define-syntax (g stx)
      (syntax-case stx ()
        ([_ arg]
         #'(display arg))))

    (define display 1)

    (g 3)
将引发异常。如何解释这两种情况之间的区别

  • 如何定义这样的宏

    我想定义一个宏来允许racket中的匿名递归函数。 此选项不起作用,因为模块中未定义recur:


  • 如何实现这一点?

    为了回答您的第一个问题,您在这里忘记的是,当您这样定义一个模块级别的
    时,该定义将适用于整个模块。因此,理论上,您可以这样编写第二个代码块:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    现在可以理解为什么会出现错误,因为宏中的显示绑定到
    1
    ,这不是函数

    长话短说,把卫生看作是词汇范围。定义宏时,
    display
    绑定到的内容就是它的内容。(这与其他语言中的宏相反,在其他语言中,无论调用(或真正展开)宏时显示的是什么,它都将是什么


    现在,为了回答你的第二个问题,我很抱歉,但我不清楚你想问什么。如果你能把它弄清楚一点,那么我可以填写答案的这一部分。

    为了回答你的第一个问题,你在这里忘记的是,当你这样做一个模块级的
    定义
    时,这个定义对整个过程都是有约束力的所以,理论上,你可以这样写你的第二个代码块:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    现在可以理解为什么会出现错误,因为宏中的显示绑定到
    1
    ,这不是函数

    长话短说,将卫生视为词汇范围。定义宏时,无论
    display
    绑定到什么,它都将是什么。(这与其他语言中的宏相反,在其他语言中,调用(或真正扩展)宏时,无论
    display
    绑定到什么,它都将是什么


    现在,为了回答你的第二个问题,我很抱歉,但我不清楚你想问什么。如果你能把它整理一下,那么我可以填写答案的这一部分。

    那么你想打破hygene?你需要获得
    recur
    以获得原始表单的词汇上下文,这样
    recur
    就会被视为相同标识符。您可以使用
    datum->syntax
    执行此操作,结果可能如下所示:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    (定义语法(递归-λstx)
    (语法大小写stx()
    [(args body…)
    (使用语法([recur stx(基准->语法stx'recur)])
    #'(Z(λ)(重复stx)
    (λargs体…)]
    
    现在,只要您的args或body中的嵌套引入
    recur
    ,它就会工作:

    ;多参数递归
    (定义Z)
    (λ(f)
    ((λ(g)(g))
    (λ(g)
    (f(λargs(应用(g)args()()())))
    埃克曼
    ((重现-λ(mn)
    (续)
    (=m0)(+n1))
    (=n0)(重现(-m1)1))
    (其他(重复(-m1)(重复-n1(()())))
    3.
    6)
    ; ==> 509
    
    如果将
    recur
    设为参数,则此选项无效:

    ((重现-λ(重现)(重现1))1)
    错误:重复不是一个过程
    
    当然,如果进行嵌套绑定:

    ((重现-λ(a)
    (定义重复a)
    (重复1次)
    1)
    错误:重复不是一个过程
    
    当然,您可以单步通过宏扩展器,它会向您显示它的功能如下:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    (展开一次
    #'(递归-λ(mn)
    (续)
    (=m0)(+n1))
    (=n0)(重现(-m1)1))
    (其他(重现(-m1)(重现-n1(()())))
    ; ==>
    "#"(Z)
    ;(λ(重复)
    ;(λ(mn)
    (续)
    ;(=m0)(+n1))
    ;(=n0)(重复(-m1)1))
    (否则)(重复(-m1)(重复-n1(()()()))
    
    那么你想打破hygene吗?你需要获得
    recur
    以获得原始表单的词汇上下文,这样
    recur
    将被视为相同的标识符。你可以使用
    数据->语法执行此操作,结果可能如下所示:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    (定义语法(递归-λstx)
    (语法大小写stx()
    [(args body…)
    (使用语法([recur stx(基准->语法stx'recur)])
    #'(Z(λ)(重复stx)
    (λargs体…)]
    
    现在,只要您的args或body中的嵌套引入
    recur
    ,它就会工作:

    ;多参数递归
    (定义Z)
    (λ(f)
    ((λ(g)(g))
    (λ(g)
    (f(λargs(应用(g)args()()())))
    埃克曼
    ((重现-λ(mn)
    (续)
    (=m0)(+n1))
    (=n0)(重现(-m1)1))
    (其他(重复(-m1)(重复-n1(()())))
    3.
    6)
    ; ==> 509
    
    如果将
    recur
    设为参数,则此选项无效:

    ((重现-λ(重现)(重现1))1)
    错误:重复不是一个过程
    
    当然,如果进行嵌套绑定:

    ((重现-λ(a)
    (定义重复a)
    (重复1次)
    1)
    错误:重复不是一个过程
    
    当然,您可以单步通过宏扩展器,它会向您显示它的功能如下:

    #lang racket
    (let ([display 1])
      (define-syntax (g stx)
        (syntax-case stx ()
          ([_ arg]
           #'(display arg))))
    
      (g 3))
    
    (展开一次
    #'(递归-λ(mn)
    (续)
    (=m0)(+n1))
    (=n0)(重现(-m1)1))
    (其他(重现(-m1)(重现-n1(()())))
    ; ==>
    "#"(Z)
    ;(λ(重复)
    ;(λ(mn)
    (续)
    ;(=m0)(+n1))
    ;(=n0)(重复(-m1)1))
    (否则)(重复(-m1)(重复-n1(()()()))
    
    如果将这个问题分为两个独立的问题,每个问题都独立提出会更好。如果将这个问题分为两个独立的问题,每个问题都独立提出会更好。谢谢你的回答,这很有帮助。正如Sylvester所说,我真正想做的是在第二个问题中打破hygenen、 谢谢你的回答,谢谢