How do we test whether something is a reference?

£可爱£侵袭症+ 提交于 2019-12-23 13:07:48

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/7293289/how-do-we-test-whether-something-is-a-reference

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!