2011-11-03 112 views
13

我寫了一個函數來計算兩組的對稱差異(4clojure站點上的其中一個問題)。該函數通過了單元測試,但它不像我想的那樣乾淨,因爲我有重複的代碼。如何在Clojure中的函數中定義函數並引用該函數?

(fn [x y] (set (concat 
    (keep-indexed #(if (nil? (get y %2)) %2) x) 
    (keep-indexed #(if (nil? (get x %2)) %2) y)))) 

很顯然,我寧願是這樣的:

(fn [x y] (set (concat (diff x y) (diff y x)))) 

凡DIFF函數的定義和引用的「內聯」,但我不知道該怎麼做,在一個FN塊。

+2

你實際上可以在4clojure上看到其他人的答案(一旦你完成了這個問題),它應該讓你知道如何整理你自己的嘗試。 –

回答

21

使用letletfn

(fn [x y] 
    (let [diff (... function body here ...)] 
    (set 
    (concat (diff x y) (diff y x))))) 
10

之一,使得Clojure的口齒不清(和一般的功能性的語言)的功能是,函數是第一類的東西 Clojure中具體地它們是對象。當你使用(defn name [arg] ...)創建函數時,如果構建函數並將其存儲在var中,以便稍後可以從程序中的任何位置找到它。它很像這樣:

(def name (fn [arg] ...)) 

現在名稱包含一個可以廣泛訪問的函數。函數不必存儲在變量中,特別是只在函數中需要的時候。在這種情況下,將函數綁定到本地名稱更爲合理,就像Matt Fenwick的答案一樣。

(let [name (fn [agr] ...)] ...) 

letfn宏使這更優雅。 重要的部分是理解函數是存儲在事物中的對象,並且您可以選擇適合您需要的容器。

+1

你爲什麼說「重要的部分是理解函數是存儲在事物中的**對象**」?說「對象」可能會導致某人認爲你正在以面向對象的意義談論對象。我認爲小寫「對象」在這裏可能會更好。 (我明白Clojure是在JVM上實現的,許多事情都是作爲OO類和對象實現的,但我不認爲新的Clojurian必須考慮實現細節。) –

相關問題