考虑到下面的多方法-
(defmulti group-data :group-by)
(defmethod group-data :day
[kv]
(->> kv :data (group-by
(fn [kv]
(let [date (:time kv)]
(str
(month date) "-" (day date) "-" (year date)))))))
(defmethod group-data :month
[kv]
(->> kv :data (group-by
(fn [kv]
(let [date (:time kv)]
(str
(month date) "-" (year date)))))))
(defmethod group-data :year
[kv]
(->> kv :data (group-by
(fn [kv]
(let [date (:time kv)]
(year date))))))在所有这三种多方法中,唯一的区别是字符串函数。我如何创建一个高阶函数,它将只接受不同的s表达式来创建字符串?
还有什么更好的想法来减少重复的代码吗?
发布于 2013-03-04 09:10:39
有时你不需要多方法:
(def dmap {:day #(str (month %) "-" (day %) "-" (year %))
:month #(str (month %) "-" (year %))
:year #(year %)})
(defn group-data [kv]
(->> kv :data (group-by
(fn [kv]
(let [date (:time kv)]
((dmap (:group-by kv)) date))))))发布于 2013-03-04 04:39:55
最简单的答案是定义一个包含所有共享逻辑的函数,该函数接受另一个用于填充变化的“洞”的函数:
(defn helper [kv time-fn]
(->> kv :data (group-by
(fn [kv]
(let [date (:time kv)]
(timefn data))))))
(defmulti group-data :group-by)
(defmethod group-data :day
[kv]
(helper kv (fn [date]
(str (month date) "-" (day date) "-" (year date)))))
(defmethod group-data :month
[kv]
(helper kv
(fn [date]
(str (month date) "-" (year date)))))
(defmethod group-data :year
[kv]
(helper kv year))发布于 2013-03-04 04:59:22
@amalloy击败了我,但我们的解决方案的结构有点不同,所以我也添加了我的解决方案。
像往常一样,当有重复的逻辑时,是时候考虑将其包装在一个函数中了。在我们的例子中,多方法可以返回用于group-by的算法,而不是直接返回值。然后,可以将group-data编写为常规函数,该函数使用multimethod来确定它是如何分组的。
(defmulti group-by-algorithm :group-by)
(defn group-data
[kv]
(->> kv :data (group-by (group-by-algorithm kv))))
(defmethod group-by-algorithm :day
[_]
(fn [{date :time}] ; destructuring kv to save us a `let`
(str
(month date) "-" (day date) "-" (year date))))
(defmethod group-by-algorithm :month
[_]
(fn [{date :time}]
(str
(month date) "-" (year date))))
(defmethod group-by-algorithm :year
[_]
(fn [{date :time}]
(year date)))此解决方案允许算法返回任何内容,并且通常适用。然而,假设每个算法都根据日期返回一些以短划线分隔的值字符串,我们可以通过引入一个函数来进一步减少样板文件,该函数采用生成值的函数,并通过依次调用它们来生成以短划线分隔的字符串。
(defmulti fns-to-group-by :group-by)
(defn group-by-algorithm
[group-by-fns]
(fn [{date :time}]
(->>
(map #(%1 date) group-by-fns) ; Call each function on the date
(interpose "-") ; Separate by dashes
(apply str)))) ; And mush them into a string
(defn group-data
[kv]
(->> kv :data (group-by (group-by-algorithm (fns-to-group-by kv)))))
(defmethod fns-to-group-by :day
[_]
[month day year])
(defmethod fns-to-group-by :month
[_]
[month year])
(defmethod fns-to-group-by :year
[_]
[year])https://stackoverflow.com/questions/15189765
复制相似问题