I would like to redefine some functions in my program on startup according to some metadata on those functions.
I am new to clojure so I would like what is the idiomatic way to accomplish this.
What I would like to do is use a cache (like memcache) to cache results of some functions (database results). In similar way like memoize or contrib core.cache, but i would like to redefine original functions transparently to the rest of the program, according to metadata which defines the caching policy.
Java libraries usually use annotations and code generation to accomplish this. But I am wandering what is idiomatic clojure way of accomplishing this?
I have explored a few options on the internet but they don't seem too satisfactory. Binding is not what I want because it only works on the current thread. Other options seems to be using some internal java functions which I would like to avoid, or binding ns and rerefining functions with eval.
I understand that i can list the potential functions in one namespace with (keys (ns-publics 'foo)), but have not explored yet how to list non public functions and how to list available namespaces (currently loaded?) - maybe there is namespace loading hook i can use?
EDIT: This is a small example of what I have in mind. Wrap is a function that would perform caching according to origs metadata. Caching and metadata are absent from example, and both wrap and orig are in the same namespace.
(defn orig []
"OK")
(defn orig2 []
"RES 2")
(defn wrap [f & args]
(let [res (apply f args)]
println "wrap" f args "=" res
res))
(set! orig (wrap orig))
(set! orig2 (wrap orig2))
After evaluating last two forms orig and orig2 should be redefined to use wrapped versions. Unfortunately I get the following error in REPL:
java.lang.IllegalStateException: Can't change/establish root binding of: orig with set (NO_SOURCE_FILE:0)