case 或 defmulti 用于封闭世界、基于价值的调度?

case or defmulti for closed-world, value-based dispatch?

假设我有一个封闭的有效调度密钥世界;在我的具体示例中,它是 nybbles 的类型。有两种明显的方法可以定义一些基于 nybble 参数表现不同的参数的操作:

  1. 使用case,例如:

    (defn read-arg [arg-mode mem cursor]
      (case arg-mode
        0x0 [:imm 0]
        0x1 [:imm (read-fwd peek-word8 mem cursor)]
        ;; And so on
        0xf [:ram (read-fwd peek-word32 mem cursor)]))
    
  2. 使用defmulti/defmethod:

    (defmulti read-arg (fn [arg-mode mem cursor] arg-mode))
    (defmethod read-arg 0x0 [_ mem cursor] [:imm 0])
    (defmethod read-arg 0x1 [_ mem cursor] [:imm (read-fwd peek-word8 mem cursor)])
    ;; And so on
    (defmethod read-arg 0xf [_ mem cursor] [:ram (read-fwd peek-word32 mem cursor)])
    

哪种 Clojure 风格更好?如果调度是在符号而不是 nybbles 上完成的,答案会有所不同吗?

我希望在这种情况下使用 case 调度本身会快得多,以至于使任何风格上的考虑都没有实际意义——基于窄范围内的整数值调度是 [= 的最佳情况10=],真的——然后我实际上认为 case 也是 也是 更好的风格(这看起来确实像 closed-world 调度,所以最好使用发出信号的机制)。

作为进一步的评论,case "result expressions" 似乎会很短,这很好。如果不是,那么可能值得将它们分解到它们自己的函数中,以防止执行分派的方法变得太大。 (然后 JIT 将能够仅内联它发现值得内联的那些部分。)

至于如果涉及符号我是否会感觉不同,这取决于许多因素 – 性能(重要吗?基准测试有很大差异吗?),分支的数量和大小(很好为了保持整个方法的大小——出于性能和可读性的原因——所以在单独的defmethod中定义每个分支的能力可能很方便)等