2024 Clojure现状调查!中分享您的想法。

欢迎!请参见关于}页面以获取更多关于此工作方式的信息。

+1
语法和reader

我深受这个问题之苦。一个函数,根据参数重复相同的指令,除了一个元素(在这个情况下是过滤器)。我该如何优雅地解决这个问题?

(defn get-threads
  "Get all urls threads"
    ([]
     (let [comments (distinct (map (fn [comment] { :thread (:thread comment) }) @db))]
   comments))
    ([search]
     (let [comments (distinct (map (fn [comment] { :thread (:thread comment) }) @db))]
   (filter (fn [comment] (s/includes? (s/upper-case (:thread comment)) (s/upper-case search))) comments))))

2个回答

+1

一种方法是将公共代码提取出来。

(defn get-comments []
  (distinct (map (fn [comment] { :thread (:thread comment) }) 
    @db))

(defn get-threads
  "Get all urls threads"
    ([] (get-comments))
    ([search]
      (->> (get-comments)
           (filter (fn [comment]
                     (s/includes? (s/upper-case (:thread comment)) 
                                             (s/upper-case search))))

由于定义和组合函数非常容易,所以常常有很多小函数被组合起来,来构建更复杂的函数。

非常感谢
+1

在这个特定情况下,我可能会将 searchnil 值视为在 filter 调用中的“始终匹配”。

(filter (fn [comment] (or (nil? search)
                          (s/includes? (s/upper-case (:thread comment))
                                       (s/upper-case search))))
        comments)

然后可以直接调用该函数的 0 个参数版本,并用 nil 调用 1 个参数版本。

(defn get-threads
  "Get all urls threads"
  ([] (get-threads nil))
  ([search]
   (let [comments ...]
     (filter ... comments))))

另一种选择是使用 cond->>

(cond->> (distinct (map (fn [comment] ...)  @db))
  search
  (filter (fn [comment] (s/includes? ...)))

这样可以只在 search 非空时将注释传递给 filter 调用,否则将返回所有未过滤的注释。

通常情况下,如果由于可选参数导致存在多种参数类型,我会为这些可选参数选择一个“空”值,并让较低参数类型的函数调用整个参数类型的函数,同时传递这些“空”值(例如零、nil、空列表等)。然后完整的参数类型的函数将根据需要条件性地处理这些“空”值。

非常有趣,我没有想到以这种方式解决这个问题。非常感谢。
...