Domanda

For now I'm using this:

(instance? clojure.lang.IDeref x)

...but I suspect there might be a better/more idiomatic way to do this.

È stato utile?

Soluzione

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top