我正在尝试advise a number of methods在一个库中具有来自另一个库的实用函数,其中一些要建议的方法是用 (defn)
定义的有些是用 (defprotocol)
定义的.
现在我正在使用this library ,它使用 (alter-var-root)
。我不在乎我使用哪个库(或者我是否手动滚动自己的库)。
我现在遇到的问题是,协议(protocol)方法有时可以建议,有时则不能,这取决于我不太清楚的因素。
如果我定义一个协议(protocol),然后定义一个类型并内联实现该协议(protocol),那么建议似乎永远不会起作用。我假设这是因为类型直接扩展了 JVM 接口(interface)并跳过了变量。
如果在单个命名空间中定义一个协议(protocol),然后建议其方法,然后将该协议(protocol)扩展为一种类型,则该建议将不起作用。
里>如果我在单个命名空间中定义一个协议(protocol),然后将该协议(protocol)扩展为一种类型,然后建议该协议(protocol)的方法,则该建议将起作用。
我想做的是找到一种可靠工作且不依赖于未定义的实现细节的建议方法。 这可能吗?
最佳答案
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
将包含 绑定(bind) 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 类,您可以尝试 replace java method使用具有所需行为的其他方法调用(但是,当谈论替换协议(protocol)/接口(interface)方法时,事情变得更加复杂:似乎您必须在实现特定协议(protocol)/接口(interface)的每个类中替换所需的方法)。
否则,您需要为您想要建议的每个函数提供显式包装器。在这种情况下,宏可能有助于减少样板代码。
关于clojure - 在 Clojure 中建议协议(protocol)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39001967/