如何在Clojure中定义函数内的函数并引用该函数?

时间:2011-11-03 21:22:18

标签: clojure

我写了一个函数来计算两组的对称差异(4clojure站点上的一个问题)。该函数通过了单元测试,但考虑到我有重复的代码,它并不像我想的那样干净。

(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函数并将其引用为“inline”,但我不知道如何在一个fn块中执行此操作。

2 个答案:

答案 0 :(得分:22)

使用letletfn

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

答案 1 :(得分:11)

使Clojure成为lisp(以及一般的函数式语言)的一个特性是函数是Clojure中的第一类事物,特别是它们是对象。当您使用(defn name [arg] ...)创建函数时,如果构建函数然后将其存储在var中,那么您可以稍后在程序中的任何位置找到它。它很像这样:

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

现在name包含一个可以广泛访问的函数。函数不必存储在变量中,特别是如果它们仅在函数中需要。在这种情况下,将函数绑定到本地名称更有意义,就像Matt Fenwick的答案一样。

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

letfn宏使这更加优雅。 重要的是要了解功能是存储在物体中的对象,您可以选择适合您需要的容器。