我想打开给定对象的类以对其进行编码。
(defn encoded-msg-for [msg]
(case (class msg)
java.lang.Double (encode-double msg)
java.lang.String (encode-str msg)
java.lang.Long (encode-int msg)
java.lang.Boolean (encode-bool msg)
clojure.lang.PersistentArrayMap (encode-hash msg)
clojure.lang.PersistentVector (encode-vec msg)
nil "~"
)
)
当我调用
(encoded-msg-for {})
时,它返回No matching clause: class clojure.lang.PersistentArrayMap
奇怪的是,将案例放入哈希图中(类作为键,字符串作为值)非常好。
另外,
(= (class {}) clojure.lang.PersistentArrayMap)
为true。这里发生了什么比较,如何切换对象本身的类或(更好)其层次结构中的某个对象?
最佳答案
我相信case
将类名视为文字符号-不会将它们解析为实际的类:
>>> (case 'clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
1
>>> (case clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
17
这相当不直观,但是可以在Clojure的
case
中使用。无论如何,惯用的方法是使用defmulti
和defmethod
而不是打开type
:(defmulti encoded-msg class)
(defmethod encoded-msg java.util.Map [x] 5)
(defmethod encoded-msg java.lang.Double [x] 7)
>>> (encoded-msg {})
5
>>> (encoded-msg 2.0)
7
调度程序使用
isa?
谓词,该谓词可以很好地处理类型比较,尤其是可以与Java继承一起很好地工作。如果您不想使用
defmulti
,那么condp
可能会在您的用例中替换case
,因为它可以正确评估测试表达式。另一方面,它不提供恒定的时间分配。
关于class - 带类的Clojure案例陈述,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12028944/