带有类的 Clojure case 语句

2024-03-19

我想打开给定对象的类以对其进行编码。

(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

奇怪的是,将案例放入哈希映射(以类作为键,字符串作为值)效果非常好。

Also, (= (class {}) clojure.lang.PersistentArrayMap)是真的。这里发生了什么比较,我如何切换对象本身的类或(更好)其层次结构中的某些内容?


我相信case将类名视为文字符号 - 它不会将它们解析为实际的类:

>>> (case 'clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
1

>>> (case clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
17

这是相当不直观的,但它在 Clojure 中是有效的case。无论如何,惯用的方法是使用defmulti and 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, then condp可能会取代case在您的用例中,因为它正确地评估了测试表达式。另一方面,它不提供恒定时间调度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有类的 Clojure case 语句 的相关文章

随机推荐