2011-02-16 22 views
7

A quanto pare, non è possibile chiamare applicare con un costruttore di record:Costruttori di record Clojure non di prima classe?

(defrecord Foo. [id field]) 

(apply Foo. my-list) 

cede a tempo di lettura, perché non si aspetta Foo. in quel luogo.

L'unica soluzione ovvia mi veniva in mente era quella di aggiungere una funzione di fabbrica:

(make-foo [id field] (Foo. id field)) 

che può essere apply'ed naturalmente.

Mi manca qualcosa? Mi aspetterei questo da C#/Java ma ho pensato che fosse un po 'deludente in Clojure ...

+0

d'accordo che è un po 'di una stranezza, ma personalmente non è mai stato un problema come trovo le funzioni factory piuttosto utile - questo modello supporta l'uso di Clojure più idiomatico, offre maggiore flessibilità nei parametri di pre-elaborazione, consente diversi insiemi di costruttori per scopi diversi, fornisce uno strato di astrazione, ecc. – mikera

risposta

10

Circling indietro su questo post-1.3 ....

In Clojure 1.3, defrecord crea due funzioni di costruzione generati. Dato:

(defrecord Person [first last]) 

questo creerà una funzione posizionale costruttore ->Person:

(->Person "alex" "miller") 

e una funzione di mappa del costruttore map->Person:

(map->Person {:first "string"}) 

Poiché si tratta di una mappa, tutti i tasti sono opzionali e assumere un valore nullo nell'oggetto costruito.

È necessario richiedere/utilizzare queste funzioni dal ns in cui si dichiara il record, ma non è necessario importare la classe record come si farebbe quando si utilizza il costruttore della classe Java.

Maggiori dettagli:

+0

Mille grazie per l'aggiornamento! –

3

Il problema è noto e si parla molto della mailing list di Clojure. Un maggior supporto verrà probabilmente aggiunto nelle future versioni di Clojure.

Per ora è necessario utilizzare le proprie funzioni o di utilizzare https://github.com/david-mcneil/defrecord2 che supporta alcune caratteristiche come:

  • di stampa in una forma eval'able
  • fornire funzione clojure come costruttore
  • accettare parametri denominati (mappe) in costruttore
  • partecipare in pre/multi-metodo post passeggiata
6

Foo. è un costruttore di classi Java, quindi presenta i tipici vincoli di interoperabilità Java con il modo in cui viene chiamato. La creazione di una funzione di costruzione è una soluzione comune (significa anche che non è necessario importare Foo in uno spazio dei nomi diverso).

+0

Questo è un ctor di classe Java shou essere un dettaglio di implementazione? Ho visto che questo era il "nuovo" defstruct con migliori caratteristiche prestazionali. –

+0

Vorrei che fosse solo un dettaglio di implementazione ma non è (ancora) il caso. –

+0

Vedere la mia altra risposta per il post-1.3. La natura della classe Java può essere ampiamente ignorata ora. –

Problemi correlati