如何继承函数选项

时间:2016-02-26 21:16:15

标签: clojure

我编写了这个从树中获取元素的函数。它只是这个:

(defn at [address tree] (reduce nth tree address))

现在问题是nth有2个重载;如果索引超出范围则抛出异常,并且返回not-found参数而不是抛出异常的异常。

现在我可以为我的函数添加一个重载来添加这个选项:

(defn at [address tree not-found] 
  (reduce (fn [curr-tree index] (nth curr-tree index not-found))
          tree address))

我可以抱怨我必须自己明确地创建一个新函数而不是漂亮的nth

这不是真正的问题。我不应该为nth的每个重载做过载。

nth只有两个重载,但在其他时候,当我想编写类似包装器的函数时,如何将决策推迟给用户。在这个例子中,我只是包裹nth;为了保持一致,我希望at模仿nth的行为。如何继承其他功能的选项?

我从clojure的角度提出这个问题,但它可能适用于其他语言,也可能不适用于其他语言。

3 个答案:

答案 0 :(得分:3)

为什么要根据at的设计设计nth?致电at的人不应该考虑nth的超载。

at可以像@ amalloy的答案一样传递函数。但我建议从一个更简单的设计开始,然后在需要时进行重构:

(defn at
  ([address tree]
    (reduce nth tree address))
  ([address tree not-found]
    (reduce #(nth %1 %2 not-found) tree address))) 

我的理由是传递not-found值比传递函数更容易理解:

(def maybe-x (at addr tree :bummer))

;; See @amalloy's answer
(def maybe-x (at' addr tree #(nth %1 %2 :bummer))))

事实上,如果我稍后需要传递其他功能,我会创建一个新的at-by函数(参见group-by)。

答案 1 :(得分:2)

也许是这样的?

(defn at [address tree & more]
  (reduce (fn [a i] (apply nth a i more)) tree address))

& more获取用户可能提供的任何额外参数,apply将其粘贴到nth的调用结束,而不必担心nth {1}}将与他们有关。

但从风格上讲,我更喜欢写出重载。它将更好地记录您的功能支持哪些选项,并且更容易维护。

答案 2 :(得分:2)

你可以使用函数参数来调用而不是nth,然后你不关心它有多少重载,因为调用者将处理他们实际想要使用的一个重载。

(defn at
  ([address tree]
     (at address tree nth))
  ([address tree f]
     (reduce f tree address)))

(at [whatever] some-tree #(nth % %2 nil))