如何为单个数据类型创建multimethod的多个实现?
这可能不是一个很好的例子,但我希望它说明了这个想法:能够将嵌套载体视为序列:
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]]]为同一类型创建和使用多个多方法实现的一般方法是什么?
发布于 2012-12-15 01:50:03
在您的问题中,您需要调度函数类型(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)但这看起来不太好。如果有其他方法来获得函数参数的类型,那么解决方案可能会更好看。
发布于 2012-12-15 01:41:22
multimethods的思想是对“不同的参数”(不一定是不同的类型)执行“相同的操作”。如果你想对“相同的参数”进行“不同的操作”,那么多方法就不适合了,就像@DaoWen建议的那样,只使用单独的函数(甚至是单独的多方法)可能是正确的方法。
如果您有一些通过编程区分参数的方法,并且根据这些区别特征使用不同的方法实现在概念上是有意义的,那么您可以使用defmulti的dispatch-fn参数来进行区分。
作为一个简单的示例,您可以使用key :foo作为dispatch-fn,它将在作为单个参数传递给多方法的map中与key :foo关联的值上执行分派。
https://stackoverflow.com/questions/13881949
复制相似问题