【问题标题】:Why is my (guile) scheme macro evaluating its argument?为什么我的(诡计)方案宏要评估它的论点?
【发布时间】:2021-11-20 03:25:38
【问题描述】:

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

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

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

未绑定变量:bar

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

“来电者说 BAR!”

这看起来好像是在应用宏之前对参数进行评估。

【问题讨论】:

    标签: scheme guile syntax-rules


    【解决方案1】:

    你应该先尝试看看宏扩展是什么:

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

    【讨论】:

    • 我想是的,是的。本质上:意外评估发生在运行时,而不是宏扩展时间?而且,我认为这意味着如果我希望我的语法允许不带引号的参数,那么我需要将我的 if 条件更改为 (eqv? (quote word) 'bar) ?
    • 是的。调试时总是先检查宏扩展。在扩展或评估期间,您需要确定错误出现的时间。
    • 感谢调试方法。
    猜你喜欢
    • 2011-10-01
    • 2020-09-05
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    • 2015-03-18
    • 2015-09-12
    • 1970-01-01
    • 2018-05-13
    相关资源
    最近更新 更多