开发者

How do we test whether something is a reference?

For now I'm using this:

(instance? clojure.lang.IDeref x)

...but I suspec开发者_如何学Ct there might be a better/more idiomatic way to do this.


This is incorrect, you are checking if the object x implements the IDeref interface, which simply means you can dereference the object with the @ symbol. What you want is this:

 (instance? clojure.lang.Ref x)

EDIT:

(Adjusting for comments).

You can do what you suggested but this has the disadvantage of classifying objects made by other users that extend IDeref to be considered a reference type. Also consider that vars also behave as reference types but do not use the IDeref interface.

There are two good options here. You can either write a function that uses an or statement:

 (def ref? [x] 
    (or (instance? clojure.lang.Ref x)
        (instance? clojure.lang.Agent x)
        ...))

Or you can use protocols to define a new predicate. This has the advantage of being extensible.

 (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

For another example see http://dosync.posterous.com/51626638

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜