2011-11-03 11 views
13

Ho scritto una funzione per calcolare la differenza simmetrica di due set (uno dei problemi sul sito 4clojure). La funzione ha superato i test unitari, ma non è pulita come vorrei, dato che ho il codice duplicato.Come si definisce una funzione all'interno di una funzione in Clojure e si fa riferimento a tale funzione?

(fn [x y] (set (concat 
    (keep-indexed #(if (nil? (get y %2)) %2) x) 
    (keep-indexed #(if (nil? (get x %2)) %2) y)))) 

Ovviamente io preferirei qualcosa di simile:

(fn [x y] (set (concat (diff x y) (diff y x)))) 

cui è definita la funzione diff e referenziato "in linea", ma non so come fare in un blocco fn.

+2

Puoi vedere le risposte di altri popoli su 4clojure (una volta completata la domanda) che dovrebbe darti un'idea di come riordinare i tuoi tentativi. –

risposta

21

Utilizzare un let o letfn:

(fn [x y] 
    (let [diff (... function body here ...)] 
    (set 
    (concat (diff x y) (diff y x))))) 
10

Una delle caratteristiche che rende Clojure un Lisp (e un linguaggio funzionale in generale) è che funzioni sono cose di prima classe in Clojure specificamente sono oggetti. Quando si crea una funzione con (defn name [arg] ...) se si crea la funzione e poi la si archivia in una var in modo da poterla trovare più tardi da qualsiasi punto del programma. è molto simile a questa:

(def name (fn [arg] ...)) 

ora il nome contiene una funzione che è ampiamente accessibile. Le funzioni non devono essere memorizzate in vars, specialmente se sono necessarie solo all'interno della funzione. In questo caso ha più senso legare la funzione a un nome locale come con la risposta di Matt Fenwick.

(let [name (fn [agr] ...)] ...) 

la macro letfn rende più elegante. La parte importante è capire che le funzioni sono oggetti che sono archiviati nelle cose e che puoi scegliere il contenitore più adatto alle tue esigenze.

+1

Perché hai detto "La parte importante è capire che le funzioni sono ** Oggetti ** che sono memorizzati nelle cose"? Dire "Oggetto" potrebbe indurre qualcuno a pensare che tu stia parlando di oggetti nel senso orientato agli oggetti. "L'oggetto" minuscolo, penso, potrebbe essere migliore qui. (Capisco che Clojure sia implementato sulla JVM, dove molte cose sono implementate come classi OO e oggetti, ma non penso che i nuovi clojuriani debbano necessariamente pensare ai dettagli dell'implementazione.) –

Problemi correlati