带有类的 Clojure 案例语句 [英] Clojure case statement with classes

查看:32
本文介绍了带有类的 Clojure 案例语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to switch on the class of a given object in order to encode it.

(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

When I call (encoded-msg-for {}), it returns No matching clause: class clojure.lang.PersistentArrayMap

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

What is odd is that putting the cases into a hash-map (with the classes as keys and strings as values) works perfectly well.

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

Also, (= (class {}) clojure.lang.PersistentArrayMap) is true. What comparison is happening here and how can I switch either on the class of the object itself or (better) something in its hierarchy?

推荐答案

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

I believe case treats the class names as literal symbols - it does not resolve them to actual classes:

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

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

这是相当不直观的,但它适用于 Clojure 的 case.无论如何,惯用的方法是使用 defmultidefmethod 而不是打开 type:

This is rather unintuitive, but so it works in Clojure's case. Anyway, the idiomatic way is to use defmulti and defmethod instead of switching on 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 继承.

The dispatcher uses the isa? predicate which deals well with the comparisons of types, in particular it works well with Java inheritance.

如果您不想使用 defmulti,则 condp 可能会在您的用例中替换 case,因为它会正确评估测试-表达式.另一方面,它不提供恒定的时间调度.

If you don't want to use defmulti, then condp might replace case in your use case, as it properly evaluates the test-expressions. On the other hand it doesn't provide constant time dispatch.

这篇关于带有类的 Clojure 案例语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆