cultura Clojure è fortemente a favore dei tipi di dati grezzi. Giustamente. Ma i tipi espliciti possono essere utili. Quando i tuoi semplici tipi di dati diventano sufficientemente complessi e specifici, hai essenzialmente un dataype implicito senza le specifiche.
Affidatevi a costruttori. Sembra un po 'sporco, in un modo OOP, ma un costruttore non è altro che una funzione che crea il tipo di dati in modo sicuro e conveniente. Uno svantaggio di semplici strutture di dati è che incoraggiano la creazione dei dati al volo. Quindi, invece di chiamare (myconstructor ...), cerco di comporre i miei dati direttamente. E con molte possibilità di errore, oltre a problemi se ho bisogno di cambiare il tipo di dati sottostante.
Le registrazioni sono il punto ideale. Con tutto il trambusto sui tipi di dati non elaborati, è facile dimenticare che i record fanno un sacco di cose che le mappe possono fare. Possono essere consultati allo stesso modo. Puoi chiamare seq su di loro. Puoi distruggerli allo stesso modo. La stragrande maggioranza delle funzioni che si aspettano una mappa accetterà anche un record.
I metadati non ti salveranno. La mia principale obiezione a fare affidamento sui metadati è che non si riflette nell'eguaglianza.
user> (= (with-meta [1 2 3] {:type :A}) (with-meta [1 2 3] {:type :B}))
true
Se questo è accettabile o meno dipende da voi, ma mi piacerebbe preoccuparsi di questo che introducono nuovi bug sottili.
Le altre opzioni dataype:
- DEFTYPE è solo per il lavoro di basso livello nella creazione di nuove strutture di dati finalità di base o speciali. Diversamente dalla defrecord, non porta con sé tutta la bontà del clojure. Per la maggior parte del lavoro, non è necessario o consigliabile.
- defstruct dovrebbe essere deprecato. Quando Rich Hickey ha introdotto tipi e protocolli, ha sostanzialmente affermato che la decortazione deve essere sempre preferita.
protocolli sono molto utili, anche se si sentono come un po 'di una partenza dalla (funzioni + dati) paradigma. Se ti ritrovi a creare record, dovresti prendere in considerazione la definizione di protocolli.
EDIT: ho scoperto un altro vantaggio per i tipi di dati semplici, che non erano stati evidente per me prima: se si sta facendo la programmazione web, i tipi di dati semplici possono essere convertiti da e per JSON in modo efficiente e facilmente. (Le librerie per fare questo includono clojure.data.json, clj-json e il mio preferito, cheshire). Con record e tipi di dati, il compito è notevolmente più fastidioso.
Ok, quindi ho bisogno di capire 'defrecord' e' defprotocol', posso ignorare 'defstruct', e non devo preoccuparmi troppo di' deftype'. È importante per un programma clojure, che 'defrecord' crei un codice java - nel senso che non voglio preoccuparmi di avere una classe java, ma se il clojure vuole usarne uno in privato, va bene? Ottima risposta, molto hepful. –
Bene, una mappa semplice è una classe java, come puoi vedere su https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java –
Quindi non è proprio un enorme problema che defrecord crea una classe java. Dal nostro punto di vista, usando il disco, non farà molta differenza - tranne che per la costruzione, si sentirà del tutto simile ai dati del clojure. –