質問

After reading this page. I find it hard to memorize how to use define-syntax in place of define-macro, so I want to implement define-macro (or at least find some equivalent) in mit-scheme.

Here is my (problematic) implementation:

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

And the REPL complained:

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

I'm new to scheme and have no idea about what is wrong, can someone help me out?

役に立ちましたか?

解決

Firstly, you should learn to use quasiquotation, so your macro is easier to read. Like this:

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

More seriously, though, this is pretty easy to write using syntax-rules, and you really should vastly prefer it over define-macro.

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

Oh, you haven't seen define-syntax-rule before? It's a simple macro you can use for writing a one-clause define-syntax macro, and it's defined so:

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

Notice how, using define-syntax-rule, simple macros become really, really easy to write. Here's another example:

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

他のヒント

If you really need define-macro semantics, you can get a reasonable approximation in mit-scheme like so:

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

You could then define my-when as:

(define-macro (my-when test . branch)
  `(if ,test (begin ,@branch)))
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top