我写了一个函数来计算两组的对称差异(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块中执行此操作。
答案 0 :(得分:22)
使用let
或letfn
:
(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
宏使这更加优雅。
重要的是要了解功能是存储在物体中的对象,您可以选择适合您需要的容器。