2024年Clojure状态调查!分享你的想法。

欢迎!有关如何工作的更多信息,请参阅关于页面。

+1
语法和读取器

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

(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个参数版本的函数调用1个参数版本的函数,并传递nil

(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非nil时,将注释传递给filter调用,否则将返回所有未过滤的注释。

通常,如果由于可选参数而具有多个参数,我会选择一个“空”值来填充可选参数,并让较低阶的参数调用完整阶的参数,传递这些“空”值(如零、nil、空列表等)。然后完整阶版将根据需要条件性地处理这些“空”值。

非常有趣,我没有想到这个解决方案。非常感谢。
...