Reputation: 3434
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?
Upvotes: 2
Views: 2291
Reputation: 51
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)))
Upvotes: 3
Reputation: 223023
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 ...))
Upvotes: 7