【问题标题】:is it possible to implement "define-macro" in mit-scheme是否可以在 mit-scheme 中实现“define-macro”
【发布时间】:2013-03-21 15:45:54
【问题描述】:

读完this page。我发现很难记住如何使用 define-syntax 代替 define-macro,所以我想在 mit-scheme 中实现 define-macro(或至少找到一些等价物)。

这是我的(有问题的)实现:

(define-syntax define-macro
  (rsc-macro-transformer
    (let ((xfmr (lambda (macro-name macro-body)
      (list 'define-syntax macro-name
        (list 'rsc-macro-transformer
          (let ((m-xfmr macro-body))
            (lambda (e r)
              (apply m-xfmr (cdr e)))))))))
      (lambda (e r)
        (apply xfmr (cdr e))))))

(define-macro my-when
  (lambda (test . branch)
    (list 'if test (cons 'begin branch))))

(my-when #t
  (begin
    (display "True")
    (newline)))

REPL 抱怨:

;The object (lambda (test . branch) (list (quote if) test (cons (quote begin) branch))) is not applicable.

我是新手,不知道哪里出了问题,有人可以帮我吗?

【问题讨论】:

    标签: scheme mit-scheme


    【解决方案1】:

    首先,您应该学会使用 quasiquotation,这样您的宏就更易于阅读。像这样:

    (define-macro (my-when test . branch)
      `(if ,test
         (begin ,@branch)))
    

    不过,更严重的是,使用syntax-rules 编写它非常容易,你真的应该非常喜欢它而不是define-macro

    (define-syntax-rule (my-when test branch ...)
      (if test
        (begin branch ...)))
    

    哦,你以前没见过define-syntax-rule?这是一个简单的宏,可用于编写单子句 define-syntax 宏,它的定义如下:

    (define-syntax define-syntax-rule
      (syntax-rules ()
        ((define-syntax-rule (name . pattern) template)
         (define-syntax name
           (syntax-rules ()
             ((name . pattern) template))))))
    

    注意,使用define-syntax-rule,简单的宏如何变得非常非常容易编写。这是另一个例子:

    (define-syntax-rule (let ((name value) ...)
                          expr ...)
      ((lambda (name ...)
         expr ...)
       value ...))
    

    【讨论】:

    • +1,特别是关于简单使用语法规则的建议。它很卫生,可以让您不必在以后调试一些非常可怕的错误。
    • 谢谢,我以前没听说过define-syntax-rule。它确实简化了代码。但是在这里我遇到了一个问题:当我尝试评估(define-syntax-rule (my-when test branch) (if test (begin branch))) 时,它显示;Unbound variable: test。顺便说一句,我的方案版本是 mit-scheme 9.0.1
    • @Javran 你运行了我粘贴的(define-syntax define-syntax-rule ...) 吗?你需要先这样做。
    • 对不起,我以为它已经被定义了。现在可以了,提前谢谢你!
    • @Javran 在一些 Scheme 实现中,比如 Racket 和 Guile,它已经被定义了。在 MIT 计划中,我想情况并非如此。 :-) 无论如何,很高兴这有帮助。 :-)
    【解决方案2】:

    如果你真的需要define-macro语义,你可以像这样在mit-scheme中得到一个合理的近似:

    (define-syntax define-macro
      (syntax-rules ()
        ((define-macro (name . args) body ...)
         (define-syntax name
           (rsc-macro-transformer
             (let ((transformer (lambda args body ...)))
               (lambda (exp env)
                  (apply transformer (cdr exp)))))))))
    

    然后您可以将 my-when 定义为:

    (define-macro (my-when test . branch)
      `(if ,test (begin ,@branch)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      • 2011-02-01
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多