Non utilizzare XML/JSON per Clojure solo la persistenza/messaging


XML è un formato popolare di archiviazione dei dati generici, soprattutto perché il suo testo in chiaro la codifica e il corrispondente prima etichetta obbligatoria facile lettura per gli umani. Ma non è particolarmente facile per gli esseri umani per cambiare, perché è Dang così dettagliata: c'è un sacco di ridondanza nel formato. E ci sono un sacco di librerie disponibili, soprattutto in Java, per creare, analizzare e manipolare XML. Quindi, se hai iniziato con Clojure, e la necessità di conservare o trasferire i alcuni dati attraverso un confine JVM (ad esempio, il disco, o un altro programma Clojure in una presa di corrente), difficilmente può essere incolpato per decidere che XML è una perfetta vestibilità. Basta prendere ccprxml a scrivere, e c.zip per l'analisi, e avere uno scoppio, giusto?




Più facile di Java

Ed è vero, questo non sarebbe poi così male. Certamente richiede meno lavoro che fare lo stesso in Java. Se avete bisogno di condividere i dati con altri linguaggi di programmazione, può anche essere l'opzione migliore (anche se JSON può essere migliore a seconda delle circostanze). Ma Clojure è un Lisp, il che significa che le strutture di dati Clojure sono ancora più facili da analizzare XML o JSON, e fanno di questa funzionalità è incorporata nel linguaggio senza fare affidamento su una libreria secondario.

Scrivi a pr-str e spiedo

clojure.core ha incorporato un pr la funzione, scrivere qualsiasi struttura incorporata Clojure dati (annidato profondo come si vuole, ovviamente) in un formato leggibile macchina. Può associare * Uscita * per uno scrittore per il file che si desidera scrivere, quindi la struttura di dati semplicemente pr, oppure è possibile utilizzare pr-str per ottenere il risultato in una stringa e quindi usare spiedo per inviare l'output in un file.

Per l'alta fedeltà ultra, è possibile associare * Print-dup * a true durante la stampa, e Clojure fare uno sforzo supplementare per garantire che l'uscita può essere letto. Non consiglio questo approccio generale, tuttavia, perché porta in un file meno leggibile, e raramente necessarie.

Leggendo con yum, leggere e leggere stringhe

L'inverso di saliva è bere rumorosamente: leggere un intero file in una singola stringa. Quindi è possibile utilizzare lettura-string per trasformare i personaggi in una struttura di dati Clojure significativo. Oppure si può ignorare la catena fase interamente dal sindacato * In * Un giocatore nel file, e chiamando leggere direttamente. Per i file di configurazione di potere reale, si può anche scegliere di eval struttura dati che sono stati letti in, dando efficacemente il file di configurazione della lingua tutta la potenza di Clojure, consentendo agli utenti di utilizzare lasciare blocchi per evitare blocchi duplicati, a le espressioni per generare valori di configurazione ripetitive, e così via.

insieme: un esempio

user => (def config {: taglia 10 Nome 'dave, Amici ['Charles' nancy]}) # 'Utente/config user => (saliva "config.clj" config) zero user => (mmm "config.clj") "{: 10 Formato: nome, Dave, amici [charles nancy]}" user => (config2 def (lettura-string (yum "config.clj"))) # 'Utente/config2 user => config2 {Size 10,: NOME, Dave: Amici [charles nancy]} user => (= config config2) vero

Argomenti avanzati: il multimethod print-dup

L'idea alla base di print-dup sta scrivendo valori come forme che possono essere letti in modo affidabile nella produzione di valori identici. Ciò è utile per valori che non possono essere espressi convenientemente come una lista, vettore o hash mappa. Come posso stampare una versione leggibile di un java.util.Date? Si può semplicemente digitare "(Data 1 2 3):" Perché è una lista di quattro elementi, non un vero e proprio oggetto Date; non sarà valutato il codice quando viene letto da lettura-string.

Clojure fornisce un gancio sull'unità per consentire oggetti arbitrari di integrarsi efficacemente nel codice come se fossero letterale: una forma che assomiglia # = (un codice) sarà non Camera di essere di nuovo in una lista; Invece, il codice viene eseguito, e un riferimento all'oggetto è incluso nella struttura dati risultanti restituiti da leggere. Se è necessario disabilitare questo per motivi di sicurezza (che consentono in qualsiasi momento l'inserimento di codice è chiamato leggere), è possibile associare * Read-eval * per falso quando si sta leggendo.

Molti tipi di dati inseriti in Clojure possibile stampare automaticamente essere letti, se si collega * Print-dup * per chiedere loro. Ad esempio, gli oggetti namespace:

User> (PR [1 * 2 * ns]) [1 # 2] nil User> (lettura-string (con-out-str (PR [1 febbraio ns *]))) ; Classificazione interrotto. User> ([stampato dup * * reale] (PR [1 * 2 * ns] vincolante)) [1 = 2 # (ns trovare l'utente)] nil User> (lettura-string (con-out-str (binding [* print-dup * vero] (Pr [1 febbraio ns *])))) [1 # 2]

rotolare la tua

Ma gli oggetti java.util.Date non sanno nulla di Clojure, e non si può pretendere di premere se stessi in modo che il lettore possa capire. Inserisci stampa multimethod DUP: print-DUP definito in clojure.core: se l'applicazione di questo multimethod per la classe che ti interessa, allora verrà chiamato quando qualcuno chiede si aggiunge una versione leggibile del modulo:

User> (java.util.Date import) java.util.Date User> (PR-str (. Data 1 2 3)) "#" User> (lettura-string (pr-str (Date. 1 2 3))) java.lang.Exception: formare illeggibile User> (vincolante [* stampa * DUP vero] (pr-str (java.util.Date. 1 2 3))) java.lang.IllegalArgumentException: Nessun metodo multimethod 'valore shipping print-dup ": class java.util.Date User> (defmethod print-dup Data [D OUT] (.WRITE Out (Str = "#" `(Date. ~ (.getYear D) ~ (.getMonth D) ~ (.getDate D))))) # User> (vincolante [* stampa * DUP vero] (lettura-string (pr-str (Date. 1 2 3)))) #

(0)
(0)

Commenti - 0

Non ci sono commenti

Aggiungi un commento

smile smile smile smile smile smile smile smile
smile smile smile smile smile smile smile smile
smile smile smile smile smile smile smile smile
smile smile smile smile
Caratteri rimanenti: 3000
captcha