I would like to redefine some functions in my program at startup according to some metadata of these functions.
I'm new to clojure, so I would like what an idiomatic way to accomplish this.
I would like to use a cache (e.g. memcache) to cache the results of some functions (database results). Similar to memoize or contrib core.cache, but I would like to redefine the original functions transparently for the rest of the program, according to the metadata that defines the cache policy.
Java libraries typically use annotations and code generation for this. But I'm wandering, what is an idiomatic way to achieve this?
I have studied several options on the Internet, but they do not seem too satisfactory. Binding is not what I want, because it only works with the current thread. Other options seem to use some internal java functions that I would like to avoid, or bind ns and override functions with eval.
I understand that I can list potential functions in one namespace using (keys (ns-publics' foo)), but have not yet studied how to list non-public functions and how to list available namespaces (currently loading?) - maybe there is a namespace loading hook that i can use?
EDIT: This is a small example of what I mean. Wrap is a function that caches according to origs metadata. Caching and metadata are missing in the 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 the last two forms, orig and orig2 must be redefined to use wrapped versions. Unfortunately, I get the following error in the REPL:
java.lang.IllegalStateException: Unable to change / set root binding: orig with set (NO_SOURCE_FILE: 0)