假设我们有一个多重方法foo
。它有几个实现。比方说,其中一人时的参数被称为foo
是一个包含字符的字符串\r
,当争论的另一个执行foo
是包含字符的字符串\!
。伪代码:
(defmulti foo ???) ; can't come up with function..
(defmethod foo \r [_]
(println "one"))
(defmethod foo \! [_]
(println "two"))
因此,当我们这样调用函数时:
(foo "right!") ;; desired output:
one
two
;; => nil
这里重要的是,受支持的方法列表应该不是固定的,而是可以扩展的,因此以后可以添加新方法而无需触及原始代码。
尽管最近几天我提高了Clojure的技能,但我仍然缺乏经验。我最好的主意是将一对地图保留为“字符-功能”,然后手动遍历它并执行正确的功能。在这种情况下,我还需要一些接口来注册新功能,等等。什么是惯用的解决方案?
我认为多重方法无法像您期望的那样起作用。
那就是:对于一次多方法调用,多方法中的调度仅被调用一次,因此,除非您定义一个实现,否则无法获得您期望的结果(将“正确”打印为“一个”和“两个”)。实际上处理在输入字符串中同时包含\r
和的情况,\!
并输出所需的输出。
这将不容易扩展。
实现您想要的更好的方法是通过迭代输入字符串来显式地进行多个调用:
; You want the dispatch function to just return the character passed to it.
(defmulti foo identity)
; The argument list here is mandatory, but we don't use them at all, hence '_'
(defmethod foo \r [_]
(println "one"))
(defmethod foo \! [_]
(println "two"))
; You need the default case for all the other characters
(defmethod foo :default [_]
())
; Iterates the string and executes foo for each character
(defn bar [s]
(doseq [x s]
(foo x)))
所以打电话
(bar "right!")
将打印:
one
two
编辑
如果您需要访问多方法主体内的整个字符串,则将其与字符一起显式传递:
; You want the dispatch function to just return the character passed to it as the first arg.
(defmulti foo (fn [c _] c))
(defmethod foo \r [c s]
(println "one"))
(defmethod foo \! [c s]
(println "two"))
; The default now takes two arguments which we ignore
(defmethod foo :default [_ _] ())
; Iterates the string and executes foo for each character
(defn bar [s]
(doseq [x s]
(foo x s)))
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句