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
精彩评论