1

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.

beguiler
  • 13
  • 3

1 Answers1

1

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))))))
rajashekar
  • 3,460
  • 11
  • 27
  • I think so, yes. Essentially: the surprise evaluation was happening at runtime, not macro-expansion time? And, I think this means that if I want my syntax to allow unquoted arguments, then I'll need to change my if-condition to `(eqv? (quote word) 'bar)` ? – beguiler Sep 28 '21 at 04:51
  • Yes. When debugging always check the macro expansion first. You need to be sure when the bug is, during expansion or evaluation. – rajashekar Sep 28 '21 at 04:53
  • Thanks for the debugging method. – beguiler Sep 28 '21 at 04:54