如何将空集合的 return 值传递给 Clojure 函数

How to return value for empty collection passed to Clojure function

我有一些函数 return 对传递的映射中的某些键的最大值。当传递的集合为空时,我想 return 0 。当然我可以使用一些条件来实现它,但想知道是否有更高级的技术?

(defn max-id [c]
  "Using as: (max-id [{ :id 1 }, { :id 2 }])"
  (if (empty? c)
    0
    (apply max (map :id c))))
;;;
(max-id []) => 0
(max-id [map-one map-two]) => 1024

具有讽刺意味的是,"advanced" 是大多数高级程序员在可能的情况下往往会避免的东西,通常会在可能的情况下选择简单性。这里的底线是您的函数运行良好,原因之一是:您的意图很明确。每个人都可以理解如果传入一个空集合会发生什么,即使他们不是程序员。这是一个巨大的好处,并且使您的解决方案已经是一个理想的解决方案,至少就空收集箱而言是这样。

现在,如果您可以保证给定集合中至少有一个 :id 为零或更大的约束(即,我们正在处理正 id) ,那么你可以这样做:

(defn max-id [c]
  (reduce max 0 (map :id c)))

但是,如果您有一个地图列表,其中 所有 都有一个负 ID,即:[{:id -1} {:id -2}],在这种情况下最大- id 应该是 -1,所以上面没有给出正确的答案。

还有其他解决方案,但它们涉及条件检查,即使它更加隐含。例如:

(defn max-id [c]
  (apply max (or (not-empty (map :id c)) [0])))

我不推荐的一个选项是将 max 替换为一个函数,该函数接受 0 个或多个参数,检查是否有任何参数,如果有则调用 max,并且returns 0 如果没有。除非你有一些其他用例需要 nothingmax 为零,否则我会避免这样做,所以我什至不会去 post 它。这变得过于复杂,需要读者去挖掘,所以不要这样做。

顺便说一句,有一个不是很为人所知的核心函数,可以说它更适合在列表中查找对于给定键其值最大的元素。它被称为 max-key:

(defn max-id [c]
  (:id (apply max-key :id c)))

但是,如果没有其他原因,只是 max-key 不如 maxmap 广为人知,我会说您的函数更容易理解。所以,这里只是给你一个额外的选择。