I have a bunch of functions that map to and from some codes defined by an external system:
(defn translate-from-ib-size-tick-field-code [val]
(condp = val
0 :bid-size
3 :ask-size
5 :last-size
8 :volume))
(defn translate-to-ib-size-tick-field-code [val]
(condp = val
:bid-size 0
:ask-size 3
:last-size 5
:volume 8))
I’d like to make a macro to remove the duplication:
#_ (translation-table size-tick-field-code
{:bid-size 0
:ask-size 3
:last-size 5
:volume 8})
I started the macro like this:
(defmacro translation-table [name & vals]
`(defn ~(symbol (str "translate-to-ib-" name)) [val#]
(get ~@vals val#)))
The resulting function body seems right, but the function name is wrong:
re-actor.conversions> (macroexpand `(translation-table monkey {:a 1 :b 2}))
(def translate-to-ib-re-actor.conversions/monkey
(.withMeta (clojure.core/fn translate-to-ib-re-actor.conversions/monkey
([val__10589__auto__]
(clojure.core/get {:a 1, :b 2} val__10589__auto__))) (.meta ...
I’d like the “translate-to-ib-” to appear as part of the function name, instead of a prefix to the namespace, as it turned out.
How can I do this with clojure macros? If I am just doing it wrong and shouldn’t use macros for this for some reason, please do let me know, but I would also like to know how to create function names like this to just improve my understanding of clojure and macros in general. Thanks!
The macro issue is twofold:
1) You’re using a backtick when quoting the form passed to
macroexpand, which namespace-qualifies the symbols within:where
foo.baris whatever namespace you’re in.2) You’re constructing the name of the
defnitem using the symbolname, which, when it is namespace-qualified, will stringify to “foo.bar/monkey”. Here’s a version that will work:Notice that we’re getting the name of
tnamewithout the namespace part, using thenamefunction.As for whether a macro is the right solution here, probably not 🙂 For a simple case like this, I might just use maps:
If speed is of the essence, check out
case.