2012-02-09 18 views
6

Per esempio, risolvendo il seguente problemaIn Clojure, è possibile definire una funzione anonima all'interno di una funzione anonima?

http://projecteuler.net/problem=5

mi si avvicinò con la soluzione seguente

(defn div [n] (= 0 (reduce + (map #(mod n %) (range 1 21))))) 
(take 1 (filter #(= true (div %)) (range 20 1e11 20))) 

Supponiamo per un certo divertimento golf desidero unire la prima linea come una funzione anonima in seconda linea. La lingua supporta questo?

+0

È possibile riscrivere la soluzione in modo più efficace. Vedi la mia risposta qui sotto. – viebel

risposta

17

Sì, ma non è possibile nidificare i moduli di macro lettore #(), è necessario utilizzare il modulo (fn).

Ad esempio:

(#(#(+ %1 %2) 1) 2) 

non funziona, perché non c'è modo di fare riferimento agli argomenti delle funzioni anonime esterni. Questo viene letto come la funzione esterna che prende due argomenti e la funzione interna prende argomenti zero.

Ma è possibile scrivere la stessa cosa con (fn...) s:

user=> (((fn [x] (fn [y] (+ x y))) 1) 2) 
3 

È inoltre possibile utilizzare il modulo #() per una delle due funzioni anonime, ad esempio:

user=> (#((fn [x] (+ x %)) 1) 2) 
3 

Così si può inline la tua funzione div come questa (notare che abbiamo dovuto cambiare il modulo #() passato a map in un modulo (fn)):

#(= true (= 0 (reduce + (map (fn [x] (mod % x)) (range 1 21))))) 
+7

Come regola generale: 'fn' è la sintassi per definire una funzione anonima, non' #() '. '#()' è solo una comodità per chiamate di funzioni semplici come '# (mod% x)' dove 'fn' aggiungerebbe molto rumore. Per le funzioni con un corpo più lungo 'fn' dovrebbe essere preferito. – kotarak

0

Si potrebbe riscrivere la soluzione in un modo molto più semplice e più efficiente (x2 più veloce!)

(defn div [n] (every? #(= 0 (mod n %)) (range 1 21))) 
(take 1 (filter div (range 20 1e11 20))) 

Il motivo è più efficiente perché every? non avrebbe attraversare la lista completa, ma piuttosto fermare quando uno degli elementi della lista è falso.

+0

Oppure potresti risolverlo circa 10 volte più velocemente evitando completamente la forza bruta. . . – ruakh

+0

Infatti. Ma stavo considerando eventuali miglioramenti relativi al "clojure" non matematici. – viebel

Problemi correlati