Clojure ha gen-class, reify, proxy e anche deftype e defrecord per definire nuovi tipi di dati di classe. Per un linguaggio che valorizza la semplicità sintattica e aborre la complessità inutile, sembra un'aberrazione. Qualcuno potrebbe spiegare perché è così? Potrebbe essere sufficiente la defchass in stile Lisp comune?Perché Clojure ha 5 modi per definire una classe invece di una sola?
risposta
Questa è una miscela di tre diversi fattori:
- Il particolare tipo di sistema del jvm
- La necessità di semantica leggermente differente per i diversi casi di utilizzo nel definire i tipi
- Il fatto che alcuni questi sono stati sviluppati in precedenza, e alcuni più tardi, mentre la lingua si è evoluta.
Quindi, prima consideriamo cosa fanno. deftype e gen classe sono simili in quanto entrambi definiscono una classe con nome per la compilazione in anticipo. La classe Gen è arrivata per prima, seguita da deftype in clojure 1.2. Deftype è preferito e ha caratteristiche di prestazione migliori, ma è più restrittivo. Una classe deftype può essere conforme a un'interfaccia, ma non può ereditare da un'altra classe.
reificare e delega sono entrambi usati per creare dinamicamente un'istanza di una classe anonima in fase di esecuzione. Il proxy è arrivato per primo, reify è arrivato insieme a deftype e defrecord nel clojure 1.2. Reify è preferito, proprio come lo è deftype, dove la semantica non è troppo restrittiva.
Questo lascia la domanda sul perché sia deftype che defrecord, poiché sono apparsi allo stesso tempo e hanno un ruolo simile. Per la maggior parte degli scopi, vorremmo usare defrecord: ha tutte le varie qualità del clojure che conosciamo e amiamo, la sequenzialità e così via. Deftype è concepito per essere utilizzato come componente elementare di basso livello per l'implementazione di altre strutture dati. Non include le normali interfacce clojure, ma ha la possibilità di campi mutabili (sebbene questo non sia l'impostazione predefinita).
Per approfondimenti check out:
The clojure.org datatypes page
The google group thread where deftype and reify were introduced
La risposta breve è che tutti hanno scopi diversi e utili. La complessità è dovuta alla necessità di interoperare efficacemente con le diverse funzionalità della JVM sottostante.
Se il numero di telefono non ha bisogno di interoperabilità Java allora il 99% delle volte è meglio attenersi a uno defrecord oa una semplice mappa Clojure.
- Usa defrecord se si desidera utilizzare protocolli
- Altrimenti una mappa regolare Clojure è probabilmente più semplice e più comprensibile
Se le vostre esigenze sono più complesse, quindi il seguente diagramma di flusso è un ottimo strumento per spiegando il motivo per cui si dovrebbe scegliere una di queste opzioni sulle altre:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
grazie mille per il collegamento al diagramma di flusso. Aiuta che il blog sia del coautore di O'reilly's - Programming Clojure. Penso che questo processo decisionale sia piuttosto complesso. Le differenze tra l'interfaccia e la classe concreta o la necessità di definire metodi statici o non denominati o di tipo anonimo sono talmente vaste da richiedere un diverso costrutto linguistico? – Salil
le differenze non sono vaste, ma sono * filosoficamente differenti * in termini di ciò che stai cercando di ottenere. Penso che i molteplici approcci in Clojure riflettano queste differenze sottostanti, che è una buona ragione per cui dovrebbero essere dati nomi diversi. – mikera
+1. Non avevo mai visto quel diagramma di flusso prima, è fantastico. –
- 1. Creazione di una classe Python per "una sola istanza"?
- 2. CLGeocodeCompletionHandler ha una sola voce di segnaposto
- 3. Altri modi di controllare se una classe ha una certa funzione di membro di controllo
- 4. La classe <SomeObject> ha una sola istanza?
- 5. Implementare un listener per una Classe invece di un'istanza
- 6. Perché C++ ha un ";" dopo una dichiarazione di classe
- 7. Clojure ha una logica di cortocircuito?
- 8. Come creare una macro per definire due funzioni in clojure
- 9. Modi moderni per dichiarare una classe in php
- 10. Perché utilizzare definire la parola chiave per definire una funzione
- 11. Il modo migliore per definire una classe immutabile nell'obiettivo C
- 12. Come definire una convenzione di denominazione personalizzata se EF 5
- 13. Modi per trovare una condizione di gara
- 14. Perché una classe modello derivata non ha accesso agli identificatori di una classe modello di base?
- 15. Il clojure ha una stringa raw?
- 16. Come definire gli operatori di sottoinsiemi per una classe S4?
- 17. In Clojure, è possibile definire una funzione anonima all'interno di una funzione anonima?
- 18. Esiste una libreria .net che ha una classe Vector immutabile persistente (come trovata in Clojure/Scala)?
- 19. Come definire una classe in Python
- 20. Come definire una classe ereditare must
- 21. definisce un sinonimo per una macro Clojure
- 22. Clojure var-definire macro
- 23. Perché sovraccaricare true e false invece di definire l'operatore bool?
- 24. Does Sublime Text 2 ha una modalità di sola lettura?
- 25. Posso definire un __repr__ per una classe piuttosto che un'istanza?
- 26. R: come definire più costruttori per una classe R6?
- 27. Selezionare gli elementi con una sola classe in JQuery
- 28. Come posso rendere immutabile una classe Java in Clojure?
- 29. Perché la classe di classe Data.String.IsString definisce solo una conversione?
- 30. È appropriato definire una classe di caso Scala non banale?
Il thread di gruppo di google è stato molto prezioso. La mia comprensione è per il proxy java-interop, la classe gen è soppiantata principalmente da reify e deftype. Sono lieto di avere meno metodi "consigliati" per definire i tipi ora. – Salil
Ottima risposta, e grazie per il collegamento al thread. –
Mi spiace, cosa significa "sequenzialità"? Google non aiuta ... – Trylks