13

我是 clojure 的新手,我见过这样写的匿名函数:

(fn [x] (* x x))

并且还喜欢:

#(* % %)

显然,第二种更简洁。有什么相关的区别吗?每个匿名函数都可以用任何一种风格表示吗?是更惯用的一种吗?

与这个问题相关,我无法确定如何转换(fn [x] [x x])为后一种语法。我将不胜感激指向澄清这种情况的文档的指针。

4

3 回答 3

21

最重要的区别是:

  • (fn ...)可以嵌套,#()不能
  • 您可以使用(fn [x y] ..)或类似名称更好地命名您的参数,而不是使用%,%2%3
  • 您可以为递归使用命名函数(fn ...),例如(fn fib [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
  • (fn [...] ...)由于#()是阅读器宏而不是常规的 Clojure 形式,因此更容易进行代码生成/操作。
  • #()更简洁。但是,如果这是一个主要考虑因素,那么您的优先级可能是错误的:-)

我个人的建议是:

  • (fn [...] ...)大多数情况下更喜欢
  • 仅用于#()非常短的内联函数,例如(map #(+ 2 %) (range 10))
  • 还要考虑通过高阶函数生成匿名函数而不是显式地写出它们可能会更好,例如(comp func1 func2)(partial func param1 param2)等。
于 2012-10-02T02:23:18.463 回答
5

另一个 SO 答案(Clojure 开发人员要避免的常见编程错误)提到#([% %])扩展为fn [%] ([% %])(注意括号),这会导致 ArityException。

您可以#(vector % %)解决此限制。

于 2012-10-02T02:27:54.773 回答
2

文档中,我认为这些是最相关的差异:

惯用的将用于非常短的一次性映射/过滤器 fns 等。

#() 表单不能嵌套。

另一件事是,如果您需要命名参数,fn 是一个更好的选择。对于#(),您将使用 %,或者对于多个参数,例如 %1、%2 等(还有 %&)。

于 2012-10-02T02:14:43.943 回答