Search code examples
schemeguilesyntax-rules

Why is my (guile) scheme macro evaluating its argument?


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.


Solution

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