I have a bit of a dilemma here that I can't figure out. I'm trying to create a bunch of functions that are all pretty similar except for a couple things (included the number of arguments they take).
I wrote a macro to create one of these functions that seems to be working correctly. Here's the macro
(defmacro gen-fn
[meth args transform-fns]
`(fn [~'conn ~@args]
(->> (. metadata-service
~meth
(sec/single-use-ticket ~'conn)
~@args)
~@transform-fns)))
So I can create two functions
(def get-source (gen-fn getSource [version source] [bean]))
(def get-all-sources (gen-fn getAllSources [version] [(map bean)]))
and both work correctly when I call them like this:
(get-source conn "2013AB" "WHO97")
(get-all-sources conn "2013AB")
Now I have about 600 of these functions to create so it would be nice if I could simplify this a bit (and eventually maybe read it in from an external source at application startup). So my first thought here was to construct a map like this:
(def metadata-methods
{ "getSources" [["version" "source"] ["bean"]]
"getAllSources" [["version"] ["(map bean)"]] })
or something along those lines then use doseq
or something like it to create the functions
(doseq [[function-label [args transform-fns]] metadata-methods]
(intern *ns* (symbol (->kebab-case function-label))
(gen-fn function-label [version source] [bean])))
When I run this it seems to work, but calling (get-source conn "2013AB" "WHO97")
throws an exception saying there is no matching method "function_label" for class Proxy...
So somehow the macro isn't creating the function correctly.
So my questions are 1) Is there an easy way to make this work? 2) Am I making something more complicated than it needs to be? Is there an easier way to accomplish the same thing?
A plain function would work except for the fact that each of the functions to be generated takes a different number of arguments and I really would like each of the functions to have a fixed arity.