Reputation: 12983
I have this 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
is a protocol defined in a clojurescript dependency, with a process-message
function.
When I try to use widget
like so
(ns my.cljs.ns
(:require-macros [my.ns.macros :as macro])
(:require [petrol.core :refer [Message]]))
(macro/widget A-Record a-field :a-key)
I get this error:
Bad method signature in protocol implementation,
my.ns.macros/Message does not declare method called
process-message ...
How can I get Message to refer to petrol/Message
instead of my.ns.macros/Message
?
Upvotes: 2
Views: 103
Reputation: 10662
You need the power of the mystical ~' operator :) I see you already invoked it for process-message, so perhaps you are already acquainted with why; but for the purposes of the answer, stuff in the backtick gets fully namespace qualified, where as evaluate quote puts the literal symbol in place.
(macroexpand-1 '(widget :a :b))
And the error message indicate that you need to ~'Message
if you want to avoid it having the current ns attached to it.
However fully qualifying Message with the petrol namespace would be a good move IMO
petrol.core/Message
That way you don't need to rely on it being referred in the ns declaration. Note you don't need to ~' it either.
Also I would be wary of (~@app-key app#) because app-key are optional... you could get nothing passed in which would call whatever #app is, which doesn't sound like something you want to happen. Similarly passing more than one seems wierd to. Maybe it should be a required param?
Upvotes: 2