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
在评估 form 之后(def func-2 func-1)
, varfunc-2
将包含var的绑定func-1
(换句话说,它的值),因此advice-var
不会影响它。
尽管这样的定义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 类,您可以尝试将 java 方法替换 invoke
为具有所需行为的其他方法(但是,事情变得更多谈论替换协议/接口方法时很复杂:似乎您必须在每个实现特定协议/接口的类中替换所需的方法)。
否则,您将需要为您想要建议的每个函数提供显式包装器。在这种情况下,宏可能有助于减少样板文件。