Clojure中匿名函数的fn和#语法有区别吗?

Eri*_*son 13 syntax lambda clojure anonymous-function

我是clojure的新手,我见过匿名函数,如:

(fn [x] (* x x))
Run Code Online (Sandbox Code Playgroud)

还喜欢:

#(* % %)
Run Code Online (Sandbox Code Playgroud)

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

与此问题相关,我无法确定如何转换(fn [x] [x x])为后一种语法.我希望有一个指向文档的指针来澄清这种情况.

mik*_*era 20

最重要的区别是:

  • (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)等.


bri*_*ris 5

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

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