Clojure本身不提供任何可靠的建议功能,甚至通过def
/defn
定义的功能。请看下面的例子:
(require '[richelieu.core :as advice])
(advice/defadvice add-one [f x] (inc (f x)))
(defn func-1 [x] x)
(def func-2 func-1)
(advice/advise-var #'func-1 add-one)
> (func-1 0)
1
> (func-2 0)
0
形式(def func-2 func-1)
,VAR func-2
的评估后,将含有 VAR func-1
(换句话说,它的价值)的结合,所以advice-var
不会影响它。
Eventhough,像func-2
定义是罕见的,你可能已经注意到或使用下列内容:
(defn generic-function [generic-parameter x y z]
...)
(def specific-function-1 (partial generic-function <specific-arg-1>))
(def specific-function-2 (partial generic-function <specific-arg-2>))
...
如果你的建议generic-function
,没有具体的功能将工作,由于上述特点符合市场预期。
如果建议是你的关键,因为这可能工作,我想一个解决方案如下:因为Clojure的功能被编译成Java类,您可以尝试replace java methodinvoke
与曾期望行为的其他方法(然而,当谈论替换协议/接口方法时,事情变得更加复杂:似乎你将不得不在每个实现特定协议/接口的类中替换所需的方法)。
否则,您需要为每个想要建议的函数显式包装。在这种情况下宏可能有助于减少样板。