符号与宏中错误的命名空间相关联

Symbol is associated with the wrong namespace in a macro

我有这个宏:

(defmacro widget [msg-type value & app-key]
  `(defrecord ~msg-type [~value]
     Message
     (~'process-message [msg# app#]
      (let [state# (~@app-key app#)]
        (dissoc
         (->>
          (merge state# msg#)
          (assoc app# ~@app-key))
         :errors)))))

Message 是在 a clojurescript dependency 中定义的协议,具有 process-message 功能。

当我尝试像这样使用 widget

(ns my.cljs.ns
  (:require-macros [my.ns.macros :as macro])
  (:require [petrol.core :refer [Message]]))

(macro/widget A-Record a-field :a-key)

我收到这个错误:

Bad method signature in protocol implementation, 
my.ns.macros/Message does not declare method called 
process-message ...

如何让消息引用 petrol/Message 而不是 my.ns.macros/Message

你需要神秘的 ~' 运算符的力量:) 我看到您已经为进程消息调用了它,所以也许您已经知道原因了;但是出于答案的目的,反引号中的内容得到了完全限定的命名空间,其中评估引号将文字符号放在适当的位置。

(macroexpand-1 '(widget :a :b))

并且错误消息表明您需要 ~'Message 如果您想避免它附加当前 ns。

然而,使用 petrol 命名空间完全限定 Message 将是一个很好的举措 IMO

petrol.core/Message

这样你就不需要依赖它在 ns 声明中被引用。请注意,您也不需要 ~' 它。

我也会对 (~@app-key app#) 保持警惕,因为 app-key 是可选的...你不会得到任何传入的东西来调用 #app 是什么,这听起来不像是什么你想要发生。同样,超过一个似乎很奇怪。也许它应该是一个必需的参数?