Я хотел бы переопределить некоторые функции в моей программе при запуске в соответствии с некоторыми метаданными этих функций.
Я новичок в clojure, поэтому я хотел бы узнать, каков идиоматический способ сделать это.
Что я хотел бы сделать, так это использовать кеш (например, memcache) для кеширования результатов некоторых функций (результатов базы данных). Подобным образом, как memoize или contrib core.cache, но я бы хотел прозрачно переопределить оригинальные функции для остальной части программы в соответствии с метаданными, которые определяют политику кэширования.
Библиотеки Java обычно используют аннотации и генерацию кода для достижения этой цели. Но я забочусь о том, что такое идиоматический способ решения этой проблемы?
Я изучил несколько вариантов в Интернете, но они не кажутся слишком удовлетворительными.
Связывание не то, что я хочу, потому что оно работает только в текущем потоке.
Другие варианты, кажется, используют некоторые внутренние функции Java, которые я хотел бы избежать, или
связывание ns и переопределение функций с помощью eval.
Я понимаю, что могу перечислить потенциальные функции в одном пространстве имен с помощью (keys (ns-publics 'foo)), но еще не изучил, как перечислять непубличные функции и как перечислять доступные пространства имен (загруженные в настоящее время?) - может быть есть хук загрузки пространства имен, который я могу использовать?
EDIT:
Это небольшой пример того, что я имею в виду. Wrap - это функция, которая выполняет кэширование в соответствии с метаданными origs. Кэширование и метаданные отсутствуют в примере, и wrap, и orig находятся в одном и том же пространстве имен.
(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))
После оценки последних двух форм orig и orig2 должны быть переопределены для использования упакованных версий.
К сожалению, я получаю следующую ошибку в REPL:
java.lang.IllegalStateException: Невозможно изменить / установить корневую привязку: orig с набором (NO_SOURCE_FILE: 0)