我们如何测试某物是否是参考?

Sta*_*ris 5 clojure

现在我正在使用这个:

(instance? clojure.lang.IDeref x)

...但我怀疑可能有更好/更惯用的方法来做到这一点。

bmi*_*are 5

这是不正确的,您正在检查对象 x 是否实现了 IDeref 接口,这仅意味着您可以使用 @ 符号取消引用该对象。你想要的是这个:

 (instance? clojure.lang.Ref x)
Run Code Online (Sandbox Code Playgroud)

编辑:

(调整评论)。

您可以按照您的建议进行操作,但这有一个缺点,即对扩展 IDeref 的其他用户创建的对象进行分类以被视为引用类型。还要考虑 vars 也作为引用类型,但不使用 IDeref 接口。

这里有两个不错的选择。您可以编写一个使用 or 语句的函数:

 (def ref? [x] 
    (or (instance? clojure.lang.Ref x)
        (instance? clojure.lang.Agent x)
        ...))
Run Code Online (Sandbox Code Playgroud)

或者您可以使用协议来定义新的谓词。这具有可扩展的优点。

 (defprotocol Ireference? (reference? [this]))

 (extend-type java.lang.Object Ireference? (reference? [this] false))
 (extend-type nil Ireference (reference? [this] false))
 (extend-type clojure.lang.Ref Ireference? (reference? [this] true))
 (extend-type clojure.lang.Agent Ireference? (reference? [this] true))

 ;;user=> (reference? nil)
 ;;false
 ;;user=> (reference? (ref 0))
 ;;true
Run Code Online (Sandbox Code Playgroud)

另一个例子见http://dosync.posterous.com/51626638