2016-02-26 65 views
2

我寫了這個函數,它從樹中獲取元素。只是這個:如何繼承函數選項

(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

爲什麼你在nth的設計方面設計at?無論誰打電話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)。

2

也許這樣?

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

了任何額外的參數,用戶可能提供& more選秀權,以及apply堅持他們的呼叫nth結束,沒有你不必擔心什麼nth會與他們無關。

雖然在風格上,我寧願寫出重載。它將爲您的功能支持哪些選項提供更好的文檔記錄,並且更容易維護。

2

您可以使用函數參數來調用而不是nth,然後您不關心它有多少重載,因爲調用者將處理他們實際想要使用的一個重載。

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

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