2012-10-02 13 views
13

Sono nuovo di clojure, e ho visto funzioni anonime scritte come:C'è una differenza tra la sintassi fn e # per le funzioni anonime in Clojure?

(fn [x] (* x x)) 

e ANCHE:

#(* % %) 

Ovviamente, la seconda è più conciso. C'è qualche differenza rilevante? È possibile rappresentare ogni funzione anonima in entrambi gli stili? È un altro idiomatico?

Relativo a questa domanda, non ero in grado di determinare come convertire (fn [x] [x x]) alla seconda sintassi. Gradirei un puntatore alla documentazione che chiarisca questa situazione.

+1

#() non ha un fare implicito. (fn [] ...) sì. – Bill

+0

Per approfondire il commento di @ Bill: http://stackoverflow.com/questions/12534287/why-does-this-anonymous-function-starting-with-println-result-in-a-nullpointerex – noahlz

risposta

20

Le differenze più importanti sono:

  • (fn ...) possono essere nidificate, #() non può
  • è possibile denominare i parametri meglio con (fn [x y] ..) o simile, piuttosto che usare %, %2, %3 ecc
  • È possibile nominare una funzione con (fn ...) per l'utilizzo ricorsivo, ad es (fn fib [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
  • È più semplice eseguire la generazione/manipolazione del codice (fn [...] ...) poiché #() è una macro di lettore anziché una normale forma Clojure.
  • #() è più conciso. Ma se questo è una considerazione importante, probabilmente avete le vostre priorità sbagliato :-)

Personalmente il mio consiglio è:

  • Preferisco (fn [...] ...) nella maggior parte dei casi
  • Usa #() solo per brevissimo linea funzioni, es (map #(+ 2 %) (range 10))
  • Considerare anche che potrebbe essere preferibile generare funzioni anonime tramite funzioni di ordine superiore piuttosto che scriverle esplicitamente ad es. (comp func1 func2) o (partial func param1 param2) ecc
+1

Un'altra limitazione che vale la pena menzionare (I non sapevo se avrei potuto/dovessi modificare la tua risposta) è che 'fn' ti permette di dare un nome alla tua funzione, in modo che possano essere referenziati all'interno del corpo, come in:' (def fact (fn f [x] (if (= 1 x) 1 (* x (f (dec x)))))) ' –

+0

Apprezzo molto i suggerimenti' comp' e 'partial'. Mi chiedevo se fossero presenti, avendoli apprezzati in Haskell. –

2

Dal docs, penso che queste sono le differenze più rilevanti:

idiomatiche utilizzate sarebbe per molto brevi FNS una tantum mappatura/filtro e simili.

#() i moduli non possono essere nidificati.

Un'altra cosa è che se avete bisogno di parametri denominati, fn è una scelta migliore. Per il #() userete% o, per più i parametri, qualcosa come% 1,% 2 e così via (anche% &).

Problemi correlati