首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有多个分派值的Clojure multimethod

具有多个分派值的Clojure multimethod
EN

Stack Overflow用户
提问于 2015-03-10 18:31:24
回答 3查看 2.6K关注 0票数 6

我有一个例子,我希望multimethod中的几个分派值映射到同一个方法。例如,对于分派值1,我希望它调用method-a,而对于分派值2、3或4,我希望它调用method-b。

在Googling搜索之后,我最终编写了以下宏:

代码语言:javascript
复制
(defmacro defmethod-dispatch-seq [mult-fn dispatch-values & body]
  `(do (map
     (fn [x#] (defmethod ~mult-fn x# ~@body))
     ~dispatch-values)))

然后您可以像这样使用它:

代码语言:javascript
复制
(defmulti f identity)

(defmethod f 1 [x] (method-a x))
(defmethod-dispatch-seq f [2 3 4] [x] (method-b x))

这使您可以调用以下内容:

代码语言:javascript
复制
(f 1) => (method-a 1)
(f 2) => (method-b 2)
(f 3) => (method-b 3)
(f 4) => (method-b 4)

这是个好主意吗?

EN

回答 3

Stack Overflow用户

发布于 2015-03-10 19:32:23

我宁愿这样做:

代码语言:javascript
复制
(defn dispatch-function
  [value]
  (if (= 1 value) :case-a :case-b))

(defmulti f dispatch-function)

(defmethod f :case-a
  [x]
  :doing-something)

(defmethod f :case-b
  [x]
  :doing-something-else)

这样就避免了宏,并将调度函数用于预期的目的。

票数 5
EN

Stack Overflow用户

发布于 2015-08-29 22:08:14

这实际上正是clojure中创建层次结构的目的。defmulti采用:hierarchy参数,该参数可以建立x is a y关系。

唯一的小问题是层次结构不能与数字一起工作。例如,你不能告诉它数字0“是”:a。然而,希望你真的只是为了简单而选择数字,并提出问题,并在实际案例中可能有关键字,你可以这样做:

代码语言:javascript
复制
(def hh (-> (make-hierarchy)
            (derive :0 :a)
            (derive :1 :a)
            (derive :2 :b)
            (derive :3 :b)
            atom))

(isa? @hh :3 :b) ;; => true

(defmulti mm
          "Demo of using hierarchy"
          (comp keyword str)
          :hierarchy hh)

(defmethod mm :b [orig] {:b orig})
(defmethod mm :a [orig] {:a orig})
(defmethod mm :default [orig] :oopsie)

(mm 2) ;; => {:b 2}
(mm 1) ;; => {:a 1}
(mm 4) ;; => :oopsie
;; Cool thing is we can steer this at RUNTIME!
(swap! hh derive :4 :b)
(mm 4) ;; => {:b 4}

;; So we can keep the data close to the definition:
(mapv #(swap! hh derive % :c) [:5 :6 :7])
(defmethod mm :c [orig] {:c orig})
(mm 6) ;; => {:c 6}

备注:

  • 我使用atom而不是(var hh),因为它与clojurescript一起工作得更好(cljs不喜欢vars in clojurescript)性能应该还不错。调度函数输出的所有内容都缓存了它解析到的实际方法的映射(遍历层次结构)。
票数 5
EN

Stack Overflow用户

发布于 2015-03-10 18:58:09

因为这是一个未解决的问题(“这是个好主意吗?”)我将尝试解决脑海中浮现的两个问题:

  1. 效率:由于它会产生相同的代码,因此为不同的值键入defmethod并对它们使用相同的函数同样有效。
  2. DRY、可读性、代码质量:这比使用不同的匹配值键入n次相同的代码要好。

因此,如果这是你的函数的行为方式,这看起来是一个好主意,但是你的函数以这种方式运行的事实可能表明你的模型中有一些缺陷:

  • 你的数据(分派参数)可能会以一种更好的方式建模,以反映这种行为,或者
  • 多方法可能做得太多或做得太少,从而导致尴尬的分派调用。

在确保我的数据/函数应该如何工作之后,我会使用这样的分派机制。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28961343

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档