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