Question

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?

Était-ce utile?

La solution

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

Autres conseils

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)))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top