在 defmacro 中检查符号相等性 (Clojure)

3

这将返回false

(defmacro scratch [pattern]
  `(= 'b (first ~pattern)))

(scratch '(b))

然而,下面的输出结果是b
(defmacro scratch2 [pattern]
  `(first ~pattern))

(scratch2 '(b))

我该如何设置第一个宏使其返回true?
1个回答

4
由于宏中引入的 'b 是有命名空间的,所以会发生这种情况:
例如:
user> (defmacro nsmac []
        `(namespace 'b))

user> (nsmac)
;;=> "user"

当您传递的值不是:

user> (namespace (first '(b)))
;;=> nil

那么,您可以像这样将命名空间符号传递给宏:

user> (scratch '(user/b)) 
;;=> true

或者你可以修复你的宏,使用非命名空间符号(已知的带引号-解引号技巧):

(defmacro scratch [pattern]
  `(= '~'b (first ~pattern)))

user> (scratch '(b)) 
;;=> true

但你真正想要的是在编译时检查它,因为你拥有的这个宏最好作为普通函数,因为它不使用任何与宏相关的优点。

它可能看起来像这样:

(defmacro scratch [pattern]
  (= 'b (first pattern)))

(scratch (b))
;;=> true

有关命名空间的一些内容可以在这篇文章中找到


我的Clojure REPL在defmacro中打印有命名空间的符号时会省略它们的命名空间,否则它会同时打印命名空间。使用macroexpand是有帮助的,因为它可以实现我想要的功能。 - Michael Dawson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接