在Clojure中建议协议方法

时间:2016-08-17 16:34:38

标签: clojure advising-functions

我正在尝试使用另一个库中的实用程序函数在一个库中advise a number of methods,其中一些要建议的方法是使用(defn)定义的,而另一些是使用(defprotocol)定义的。

现在我正在使用this library,它使用(alter-var-root)。我不关心我使用哪个库(或者我是否自己动手)。

我现在遇到的问题是,协议方法有时可以被建议,有时也不能,这取决于我不太清楚的因素。

  1. 如果我定义了一个协议,那么定义一个类型并实现该协议 in-line ,然后建议似乎永远不会起作用。我假设这是因为该类型直接扩展了JVM接口并跳过了变量。

  2. 如果在一个命名空间中,我定义了一个协议,然后建议它的方法,然后将协议扩展到一个类型,建议将工作。

    < / LI>
  3. 如果在单个命名空间中,我定义了一个协议,然后将协议扩展到一个类型,然后建议协议的方法,建议工作。

  4. 我想要做的是找到一种可靠的工作方法,并且不依赖于未定义的实现细节。 这可能吗?

1 个答案:

答案 0 :(得分:2)

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的绑定(换言之,其值),因此{{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>)) ... ,由于上述特性,任何特定功能都不会按预期工作。

如果建议对您来说至关重要,作为可能工作的解决方案,我假设如下:由于Clojure函数被编译为java类,您可以尝试{{3} } generic-function和其他具有所需行为的方法(但是,当谈到替换协议/接口方法时,事情变得更加复杂:似乎你必须在实现特定协议/接口的每个类中替换所需的方法)。

否则,您需要为您想要建议的每个功能使用显式包装器。在这种情况下,宏可能有助于减少样板。