2011-11-03 35 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必须考虑实现细节。) –

相关问题