2

读完这一页。我发现很难记住如何define-syntax代替define-macro,所以我想define-macro在 mit-scheme 中实现(或至少找到一些等效的)。

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

(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.

我是计划新手,不知道出了什么问题,有人可以帮我吗?

4

2 回答 2

7

首先,你应该学会使用 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 ...))
于 2013-03-21T15:55:04.027 回答
3

如果你真的需要定义宏语义,你可以在 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)))
于 2014-06-21T00:22:33.683 回答