2016-05-05 14 views

risposta

15

reify macro consente di creare una classe anonima che estende la classe java.lang.Object e/o l'implementazione di interfacce/protocolli specificati. Gli API docs non descrivono chiaramente lo scopo, ma forniscono piuttosto i dettagli tecnici su cosa fa quella macro. Java interop documentation fornisce una breve descrizione dello scopo:

Al Clojure 1.2, reify è disponibile per l'attuazione interfacce anche.

Ancora più informazioni possono essere trovate in datatypes documentatio n dove è possibile trovare una descrizione molto dettagliata ciò che fa e come si confronta con proxy:

Mentre DEFTYPE e defrecord definire i tipi di nome, reificare definisce sia un tipo anonimo e crea un'istanza di quel tipo. Il caso d'uso è in cui è necessaria un'implementazione una tantum di uno o più protocolli o interfacce e si desidera sfruttare il contesto locale. In questo rispetto è un caso d'uso simile al proxy, o classi interne anonime in Java.

I corpi di metodo di reify sono chiusure lessicali e possono fare riferimento allo scope locale circostante . reify differisce dal proxy in quanto:

Sono supportati solo protocolli o interfacce, nessuna superclasse in calcestruzzo. I corpi metodo sono veri metodi della classe risultante, non fns esterni. L'invocazione dei metodi sull'istanza è diretta, non , utilizzando la ricerca mappa. Nessun supporto per lo scambio dinamico dei metodi nella mappa del metodo . Il risultato è una prestazione migliore rispetto al proxy, sia nella costruzione e nel richiamo di . reify è preferibile al proxy in tutti i casi dove i suoi vincoli non sono proibitivi.

+0

Non è possibile estendere una classe (diversa da 'Object') con' reify', quindi la prima frase è leggermente errata –

+0

@NathanDavis Sì, hai ragione, ho risolto la mia risposta. –

24

reify è quello di defrecord cosa fn è quello di defn.
"Ah giusto ...... quindi qual è reify"

In parole povere, i protocolli sono gli elenchi delle funzioni un tipo di dati dovrebbe sostenere, i record sono i tipi di dati e reificazioni sono tipi di dati anonimi.

Forse questo è prolisso, ma reify non può essere compresa senza capire concretamente protocolli e tipi/record: Protocolli sono un modo per utilizzare lo stesso nome per una funzione come conj che effettivamente agisce in modo diverso quando somministrato argomenti diversi ((conj [:b :c] :a) => [:b :c :a] ma (conj '(:b :c) :a) => (:a :b :c)). I record sono come oggetti o tipi (ma si comportano come mappe che li rendono più favolosi).

Più fondamentalmente, l'obiettivo è quello di risolvere "il problema Expression" che è quello di avere la capacità di senza aggiungere nuovi tipi di dati che lavorano con le funzioni esistenti, e nuove funzioni che si integrano perfettamente con i dati esistenti.

Così un giorno dici a te stesso: "Sè, dovresti imparare cosa vuol dire essere un'anatra!" così si scrive un protocollo:

(defprotocol Quacks 
    (quack [_] "should say something in ducky fashion")) 

ma è tutto troppo astratto in modo da 'reale ify' esso:

(def donald (reify Quacks 
        (quack [_] "Quacks and says I'm Donald"))) 

Ora finalmente si può sperimentare la tua creazione:

(quack donald) => "Quacks and says I'm Donald" 

Poi ti ricordi di Daffy:

(def daffy (reify Quacks 
        (quack [_] (str "Quacks and says I'm Daffy")))) 

(quack daffy) => "Quacks and says I'm Daffy" 

Ma per il momento si ricordi di Huey, a realizzare il vostro errore e definire ciò che un anatra è in un certo senso riutilizzabile:

(defrecord Duck [name] 
    Quacks 
    (quack [_] (str "Quacks and says I'm " name))) 

e fare new anatre (ci sono diversi modi per farlo):

(def huey (->Duck "Huey")) 
(def duey (Duck. "Duey")) 
(def louie (new Duck "Louie")) 

(quack huey) => "Quacks and says I'm Huey" 

ricordate che i record si comportano come le mappe (grazie a protocolli!):

(:name huey) => "Huey" 

Ma poi ti ricordi che anatre sono non sono le uniche cose che ciarlatano, in modo da scrivere un altro protocollo:

(defprotocol Walks 
    (walk [_] "should walk like a duck")) 

ed estendere la definizione di anatra

(extend-type Duck 
    Walks 
    (walk [_] "waddle waddle")) 

(walk louie) => "waddle waddle" 

Ora possiamo estendere ad altri tipi di implementare lo stesso protocollo (insegnano la stessa funzione di come lavorare con le altre cose):

Quindi diciamo che vogliamo programmatori di ciarlatano troppo :-)

(defrecord Programmer [] Quacks 
    (quack [_] "Monads are simply monoids in a category of endofunctors...")) 

(quack (Programmer.)) => "Monads are simply monoids in a category of endofunctors..." 

Raccomando questo ottimo explanation of protocols, uno explanation of reify e uno chapter on protocols in "Clojure for the Brave and True".

Declinazione di responsabilità: questo è inteso solo per dare una prima comprensione di quali protocolli sono, non migliori pratiche su come usarli. "Psst! Ho risposto a questa domanda in gran parte per insegnare a me stesso, perché fino a ieri non avevo mai scritto il mio protocollo/interfaccia!" !.

Così, mentre spero che migliora l'apprendimento qualcun altro, io vivamente benvenuto critiche o suggerimenti edit-"