2012-10-02 72 views
13

我是新來的Clojure,和我見過這樣寫匿名函數:Clojure中的匿名函數的fn和#語法有區別嗎?

(fn [x] (* x x)) 

也喜歡:

#(* % %) 

顯然,第二是更簡潔。有沒有相關的區別?每種匿名函數都可以用哪種風格表示?還有更慣用的嗎?

與此問題相關,我無法確定如何將(fn [x] [x x])轉換爲後一種語法。我希望有一個指向文檔的指針來澄清這種情況。

+1

#()沒有隱含的do。 (fn [] ...)。 – Bill

+0

詳細說明@ Bill的評論:http://stackoverflow.com/questions/12534287/why-does-this-anonymous-function-starting-with-println-result-in-a-nullpointerex – noahlz

回答

20

最重要的區別是:

  • (fn ...)可以被嵌套,#()不能
  • 您可以(fn [x y] ..)或類似的,更好的名字你的參數,而不是使用%%2%3
  • 您可以使用(fn ...)命名函數以用於遞歸使用,例如(fn fib [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
  • 由於#()是一個閱讀器宏而不是常規的Clojure格式,因此代碼生成/操作更簡單(fn [...] ...)
  • #()更簡潔。但是,如果這是一個重要的考慮因素,你可能有你的優先次序錯了:-)

個人我的建議是:

  • 在大多數情況下不想(fn [...] ...)
  • 使用#()只有很短的直列功能,例如(map #(+ 2 %) (range 10))
  • 也考慮到通過高階函數產生匿名函數而不是明確地寫出它們可能會更好, (comp func1 func2)(partial func param1 param2)
+1

另一個限制值得一提(I不知道我是否可以/應該編輯你的響應)是'fn'允許你命名你的函數,以便它們可以在body中被引用,如下所示:'(def fact(fn f [x](if (= 1 x)1(* x(f(dec x))))))' –

+0

真的很欣賞'comp'和'partial'的建議。我想知道這些是否存在,並在Haskell中表示讚賞。 –

2

docs,我認爲這是最相關的差異:

習慣使用將是非常短暫的一次性的映射/過濾FNS等。

#()表單不能嵌套。

另一件事是,如果你需要命名參數,fn是一個更好的選擇。對於#(),您將使用%或更多的參數,如%1,%2等等(還有%&)。

相關問題