Within Guile, I am trying to learn define-syntax
and syntax-rules
. I was under the impression that scheme macros do not evaluate their arguments, but it seems like mine is doing so:
(define-syntax foo
(syntax-rules ()
((foo word)
(if (eqv? word 'bar) (begin (write "Caller said BAR!") (newline)))
)))
If I call it with (foo bar)
, I get the error message
Unbound variable: bar
Whereas if I call it with (foo 'bar)
, I get the expected
"Caller said BAR!"
This makes it seem as though the argument is getting evaluated prior to application of the macro.
You should try and look at what the macro expansion is first:
scheme@(guile-user)> (use-modules (language tree-il))
scheme@(guile-user)> (tree-il->scheme (macroexpand '(foo bar)))
indented edited for clarity
(if ((@@ (#{ g184}#) eqv?) bar (quote bar))
(begin ((@@ (#{ g184}#) write) "Caller said BAR!")
((@@ (#{ g184}#) newline))))
So (foo bar)
is transformed into(after removing @@
s):
(if (eqv? bar (quote bar))
(begin (write "Caller said BAR!")
(newline)))
before evaluation happens. Now the error makes sense doesn't it?
Now what happens if you quote the word
parameter? See how this expands:
(define-syntax foo
(syntax-rules ()
((foo word)
(if (eqv? 'word 'bar) (begin (write "Caller said BAR!") (newline))))))