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

时间:2016-01-09 04:35:36

标签: clojure coding-style 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)])
    
  3. 哪种被认为是Clojure更好的风格?如果调度是在符号而不是nybbles上完成的,答案是否会有所不同?

1 个答案:

答案 0 :(得分:2)

我希望调度本身在这种情况下使用new更快,因为任何样式方面的考虑都没有 - 基于窄范围内的整数值进行调度是{{1}的最佳情况真的 - 然后我认为case 也是更好的风格(这看起来确实像封闭世界的调度,所以使用信号机制很好这一点)。

作为进一步的评论,它似乎是case"结果表达式"这里相当短,这很好。如果没有,那么可能值得将它们分解为它们自己的函数以防止执行分派的方法变得太大。 (然后JIT将能够内联它找到的那些值得内联的部分。)

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