【问题标题】:Is there a difference between the fn and # syntax for anonymous functions in Clojure?Clojure 中匿名函数的 fn 和 # 语法有区别吗?
【发布时间】:2012-10-02 01:35:27
【问题描述】:

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

(fn [x] (* x x))

也喜欢:

#(* % %)

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

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

【问题讨论】:

标签: syntax clojure lambda anonymous-function


【解决方案1】:

最重要的区别是:

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

【讨论】:

  • 另一个值得一提的限制(我不知道我是否可以/应该编辑您的回复)是fn 允许您命名您的函数,以便可以在正文中引用它们,如在:(def fact (fn f [x] (if (= 1 x) 1 (* x (f (dec x))))))
  • 非常感谢comppartial 的建议。我想知道这些是否存在,在 Haskell 中很欣赏它们。
【解决方案2】:

另一个 SO 答案 (Common programming mistakes for Clojure developers to avoid) 提到 #([% %]) 扩展为 fn [%] ([% %])(注意括号),这会导致 ArityException。

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

【讨论】:

  • 无法告诉你我为此浪费了多少时间。
【解决方案3】:

docs,我认为这些是最相关的区别:

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

#() 表单不能嵌套。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2021-12-12
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多