首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从多方法中提取共享逻辑?

如何从多方法中提取共享逻辑?
EN

Stack Overflow用户
提问于 2013-03-04 03:22:43
回答 4查看 106关注 0票数 3

考虑到下面的多方法-

代码语言:javascript
复制
(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表达式来创建字符串?

还有什么更好的想法来减少重复的代码吗?

EN

回答 4

Stack Overflow用户

发布于 2013-03-04 09:10:39

有时你不需要多方法:

代码语言:javascript
复制
(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))))))
票数 4
EN

Stack Overflow用户

发布于 2013-03-04 04:39:55

最简单的答案是定义一个包含所有共享逻辑的函数,该函数接受另一个用于填充变化的“洞”的函数:

代码语言:javascript
复制
(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))
票数 3
EN

Stack Overflow用户

发布于 2013-03-04 04:59:22

@amalloy击败了我,但我们的解决方案的结构有点不同,所以我也添加了我的解决方案。

像往常一样,当有重复的逻辑时,是时候考虑将其包装在一个函数中了。在我们的例子中,多方法可以返回用于group-by的算法,而不是直接返回值。然后,可以将group-data编写为常规函数,该函数使用multimethod来确定它是如何分组的。

代码语言:javascript
复制
(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)))

此解决方案允许算法返回任何内容,并且通常适用。然而,假设每个算法都根据日期返回一些以短划线分隔的值字符串,我们可以通过引入一个函数来进一步减少样板文件,该函数采用生成值的函数,并通过依次调用它们来生成以短划线分隔的字符串。

代码语言:javascript
复制
(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])
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15189765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档