如何为单一数据类型创建多方法的多个实现?
这可能不是一个很好的例子,但我希望它能说明这个想法:能够将嵌套向量作为序列处理:
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]]]
为同一类型创建和使用多个多方法实现的一般方法是什么?
答案 0 :(得分:1)
在您的问题中,您需要调度函数类型(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)
但这看起来并不那么好。如果有其他方法来获取函数参数类型,那么解决方案可以更好看。
答案 1 :(得分:0)
多方法的想法是你对“不同的参数”(不一定是不同的类型)进行“相同的操作”。如果你想对“相同的参数”进行“不同的操作”,那么多方法就不合适了,就像@DaoWen建议的那样,只使用单独的函数(甚至单独的多方法)可能是正确的方法。去吧。
如果你有一些以编程方式区分参数的方法,并且在概念上使用基于这些区别特征的不同方法实现,那么你可以使用defmulti
的{{1}}参数来制作区别。
作为一个简单的例子,您可以使用一个键:foo作为dispatch-fn,它将在一个映射中对与key:foo相关联的值进行调度,该映射作为多方法的单个参数传递。