如何为单个数据类型创建多方法的多个实现?
这可能不是一个很好的例子,但我希望它能说明这个想法:能够将嵌套向量都视为序列:
repl> (def thing [[[1] []] [27] [18 [32 35]]])
repl> (fmap count thing)
[2 1 2]
和树:
repl> (fmap (partial + 1) thing)
[[[2] []] [28] [19 [33 36]]]
为同一类型创建和使用多个多方法实现的一般方法是什么?
如何为单个数据类型创建多方法的多个实现?
这可能不是一个很好的例子,但我希望它能说明这个想法:能够将嵌套向量都视为序列:
repl> (def thing [[[1] []] [27] [18 [32 35]]])
repl> (fmap count thing)
[2 1 2]
和树:
repl> (fmap (partial + 1) thing)
[[[2] []] [28] [19 [33 36]]]
为同一类型创建和使用多个多方法实现的一般方法是什么?
在您的问题中,您需要发送函数类型(fmap first arg)参数。AFAIK 没有(简单的?)方法来检测任何函数的参数类型(如果错误,请纠正我)。所以你必须将它作为一些元数据添加到参数或类似的东西。例如
(defmulti fmap (fn [f _] ((comp :arg-seq? meta) f)))
(defmethod fmap true [f col]
(map-tree f col))
(defmethod fmap false [f col]
(map f col))
(fmap (with-meta inc {:arg-seq? true}) thing)
-> [[[2] []] [28] [19 [33 36]]]
(fmap (with-meta count {:arg-seq? false}) thing)
-> (2 1 2)
但这看起来不太好。如果有其他方法来获取函数参数的类型,那么解决方案可能会更漂亮。
多方法的想法是您对“不同的参数”(不一定是不同的类型)执行“相同的操作”。如果您想对“相同的参数”进行“不同的操作”,那么多方法将不适合,就像@DaoWen 建议的那样,仅使用单独的函数(甚至单独的多方法)可能是正确的方法去做吧。
如果您有某种以编程方式区分参数的方法,并且基于这些区别特征使用不同的方法实现在概念上是有意义的,那么您可以使用defmulti
'dispatch-fn
参数进行区分。
作为一个简单的例子,你可以使用一个 key :foo 作为 dispatch-fn,它会在一个 map 中与 key :foo 关联的值上进行调度,这个 map 作为单个参数传递给你的多方法。