为什么我的(诡计)计划宏评估其论点?

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

在 Guile 中,我正在努力学习 define-syntaxsyntax-rules。我的印象是方案宏不会评估他们的论点,但我的似乎正在这样做:

(define-syntax foo
    (syntax-rules ()
        ((foo word)
            (if (eqv? word 'bar) (begin (write "Caller said BAR!") (newline)))
            )))

如果我用 (foo bar) 调用它,我会收到错误消息

Unbound variable: bar

而如果我用 (foo 'bar) 调用它,我会得到预期的

"Caller said BAR!"

这使得参数看起来好像在应用宏之前得到评估。

你应该先看看宏展开是什么:

scheme@(guile-user)> (use-modules (language tree-il))
scheme@(guile-user)> (tree-il->scheme (macroexpand '(foo bar)))

为了清楚起见,进行了缩进编辑

(if ((@@ (#{ g184}#) eqv?) bar (quote bar))
    (begin ((@@ (#{ g184}#) write) "Caller said BAR!")
       ((@@ (#{ g184}#) newline))))

所以(foo bar)转化为(去掉@@s后):

(if (eqv? bar (quote bar))
    (begin (write "Caller said BAR!")
       (newline)))

在评估发生之前。现在这个错误是有道理的不是吗?

现在如果你引用 word 参数会发生什么?看看这是如何展开的:

(define-syntax foo
  (syntax-rules ()
    ((foo word)
     (if (eqv? 'word 'bar) (begin (write "Caller said BAR!") (newline))))))