首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Clojure中实现策略模式?

如何在Clojure中实现策略模式?
EN

Stack Overflow用户
提问于 2017-03-30 23:09:48
回答 2查看 267关注 0票数 2

我有三个类似的函数,它们过滤与键(列)值匹配的映射集合,不区分大小写。

以下是我想要删除的原始代码:

代码语言:javascript
运行
复制
;; gets a collection filtered by a column, exact match
(defn get-collection-by-equals [collection-name column-name column-value]
 (filter #(= (string/lower-case (column-name %)) (string/lower-case column-value)) (cached-get-collection collection-name)))

;; gets a collection filtered by a column, with partial match, case-insensitive
(defn get-collection-by-like [collection-name column-name column-value]
 (filter #(string/includes? (string/lower-case (column-name %)) (string/lower-case column-value)) (cached-get-collection collection-name)))

;; gets a collection filtered by a column, which starts with given value, case-insensitive
(defn get-collection-by-starts-with [collection-name column-name column-value]
 (filter #(string/starts-with? (string/lower-case (column-name %)) (string/lower-case column-value)) (cached-get-collection collection-name)))

你可以看到代码有多相似,我只是在每种情况下使用了不同的匹配策略,=includes?starts-with?

我的第一次尝试是这样的:

代码语言:javascript
运行
复制
;; returns a function which does a case-insensitive match between given column and value for the given map
(defn matching-fn [match-fn column-name column-value]
  (fn [map] (match-fn (string/lower-case (column-name map)) (string/lower-case column-value))))

;; gets a collection filtered by a column, exact match
(defn get-collection-by-equals [collection-name column-name column-value]
 (filter #((matching-fn = column-name column-value) %) (cached-get-collection collection-name)))

;; gets a collection filtered by a column, with partial match, case-insensitive
(defn get-collection-by-like [collection-name column-name column-value]
 (filter #((matching-fn string/includes? column-name column-value) %) (cached-get-collection collection-name)))

;; gets a collection filtered by a column, which starts with given value, case-insensitive
(defn get-collection-by-starts-with [collection-name column-name column-value]
 (filter #((matching-fn string/starts-with? column-name column-value) %) (cached-get-collection collection-name)))

我不喜欢这个解决方案的可读性,我突然想到我可以只传递匹配的函数,而不是让一个函数返回一个函数,我想出了这个:

代码语言:javascript
运行
复制
;; gets a collection filtered by a column, using the given function, case-insensitive
(defn get-collection-by-filter [collection-name filter-fn column-name column-value]
 (filter #(filter-fn (string/lower-case (column-name %)) (string/lower-case column-value)) (cached-get-collection collection-name)))

;; gets a collection filtered by a column, exact match, case-insensitive
(defn get-collection-by-equals [collection-name column-name column-value]
  (get-collection-by collection-name = column-name column-value))

;; gets a collection filtered by a column, with partial match, case-insensitive
(defn get-collection-by-like [collection-name column-name column-value]
 (get-collection-by collection-name string/includes? column-name column-value))

;; gets a collection filtered by a column, which starts with given value, case-insensitive
(defn get-collection-by-starts-with [collection-name column-name column-value]
 (get-collection-by collection-name string/starts-with? column-name column-value))

这是惯用的Clojure吗,还有其他(更好的)解决方案吗?

使用宏似乎有点过头了。

EN

回答 2

Stack Overflow用户

发布于 2017-03-31 00:16:50

像许多OO模式一样,在函数式语言中,整个模式归结为“使用带参数的函数”。提取除更改为新函数的一小部分之外的所有内容,并将更改的部分作为该函数的参数。

代码语言:javascript
运行
复制
(defn collection-comparator [cmp]
  (fn [collection-name column-name column-value]
    (let [lower-value (string/lower-case column-value)]
      (filter #(cmp (string/lower-case (column-name %)) 
                    lower-value)
              (cached-get-collection collection-name)))))

(def get-collection-by-equals (collection-comparator =))
(def get-collection-by-like (collection-comparator string/includes?))
(def get-collection-by-starts-with (collection-comparator string/starts-with?))
票数 9
EN

Stack Overflow用户

发布于 2017-03-31 05:08:21

我只使用您的get-collection-by-filter,不再包装它-为什么要为参数可能采用的每个值创建一个新函数?

旁白:只需将描述设置为文档字符串,并将其格式化:

代码语言:javascript
运行
复制
(defn get-collection-by-filter
  "gets a collection filtered by a column, using the given function,
   case-insensitive"
  [collection-name filter-fn column-name column-value]
  (filter #(filter-fn (string/lower-case (column-name %))
                      (string/lower-case column-value))
          (cached-get-collection collection-name)))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43121743

复制
相关文章

相似问题

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