Clojure 中的建议协议方法
Advising protocol methods in Clojure
我正在尝试 advise a number of methods 在一个库中使用另一个库的实用函数,其中一些要建议的方法是用 (defn)
定义的,有些是用 [=11= 定义的].
现在我正在使用 this library,它使用 (alter-var-root)
。我不在乎我使用哪个库(或者我是否手动滚动自己的库)。
我现在 运行 遇到的问题是,协议方法有时可以被建议,有时不能,这取决于我不太清楚的因素。
如果我定义一个协议,然后定义一个类型并实现该协议在线,那么建议似乎永远不会起作用。我假设这是因为该类型直接扩展了 JVM 接口并跳过了 vars.
如果在单个命名空间中,我定义了一个协议,然后通知它的方法,然后将协议扩展到一个类型,那么通知将不会工作。
如果我在单个命名空间中定义一个协议,然后将协议扩展为一个类型,然后通知协议的方法,通知 将 起作用.
我想做的是找到一种可靠的建议方法,并且不依赖于未定义的实现细节。 这可能吗?
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
不会影响它。
尽管像 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
,none 的特定功能将由于上述特殊性而按预期工作。
如果建议对您来说很重要,作为 可能 可行的解决方案,我假设如下:因为 Clojure 函数被编译为 java class 是的,您可以尝试 replace java method invoke
使用具有所需行为的其他方法(但是,在谈论替换 protocol/interface 方法时,事情变得更加复杂:似乎您必须在实现特定 protocol/interface).
的每个 class 中替换所需的方法
否则,您需要为每个要建议的函数提供显式包装器。在这种情况下,宏可能有助于减少样板文件。
我正在尝试 advise a number of methods 在一个库中使用另一个库的实用函数,其中一些要建议的方法是用 (defn)
定义的,有些是用 [=11= 定义的].
现在我正在使用 this library,它使用 (alter-var-root)
。我不在乎我使用哪个库(或者我是否手动滚动自己的库)。
我现在 运行 遇到的问题是,协议方法有时可以被建议,有时不能,这取决于我不太清楚的因素。
如果我定义一个协议,然后定义一个类型并实现该协议在线,那么建议似乎永远不会起作用。我假设这是因为该类型直接扩展了 JVM 接口并跳过了 vars.
如果在单个命名空间中,我定义了一个协议,然后通知它的方法,然后将协议扩展到一个类型,那么通知将不会工作。
如果我在单个命名空间中定义一个协议,然后将协议扩展为一个类型,然后通知协议的方法,通知 将 起作用.
我想做的是找到一种可靠的建议方法,并且不依赖于未定义的实现细节。 这可能吗?
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
不会影响它。
尽管像 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
,none 的特定功能将由于上述特殊性而按预期工作。
如果建议对您来说很重要,作为 可能 可行的解决方案,我假设如下:因为 Clojure 函数被编译为 java class 是的,您可以尝试 replace java method invoke
使用具有所需行为的其他方法(但是,在谈论替换 protocol/interface 方法时,事情变得更加复杂:似乎您必须在实现特定 protocol/interface).
否则,您需要为每个要建议的函数提供显式包装器。在这种情况下,宏可能有助于减少样板文件。