Domanda

Sono nuovo di Clojure, e sto cominciando a sperimentare con la costruzione di un'applicazione.

Finora, tutto quello che ho visto su tutorial sulla compilazione di programmi Clojure comporta l'interattività. Ad esempio, "caricare il REPL e il tipo (load-file 'questo o quello') per l'esecuzione. Questo va bene, ma non è sufficiente.

Sono così utilizzato per gli idiomi edit-compile-run di linguaggi come C o Delphi, che io istintivamente spinto a fare modifiche, poi ha colpito "M-x di compilazione".

Il problema è che "lein uberjar", che ho capito è l'equivalente di "fare", è dolorosamente lento da eseguire anche per un mondo ciao. Così sto andando ad avere per capire come questo "sviluppo interattivo" opere roba, smettere di usare l'uberjar come se fosse di marca rapido, e lo si salva solo per la fine della giornata.

Un'altra cosa che ho notato durante la costruzione (usando Lein uberjar) è che la piccola applicazione GUI Sto lavorando su pop up fotogrammi nel processo di compilazione, come se fossero l'esecuzione durante la compilazione. Sembra proprio un po 'controintuitivo per me; non è del tutto analogo a come "fare" come avevo pensato.

So che il modo Lisp di sviluppare le cose in modo interattivo lavorando in REPL, e io non sto cercando di cambiare la situazione: Vorrei adattarsi a questo modo di vivere. Purtroppo, ho visto poco in forma di documentazione su come farlo. Per esempio, come ripristinare lo stato attuale della macchina. Sembra proprio tipo di disordinato a solo continuare a compilare i singoli frammenti al volo, senza essere in grado di fare una sorta di reset.

La maggior parte dei tutorial che ho visto su Clojure (e Lisp), in generale, sembrano concentrarsi sulla pirateria informatica nel REPL. Le migliori pratiche sulla distribuzione di applicazioni rimane un mistero per me. I miei utenti sono solo andando a essere utenti; essi non saranno gli sviluppatori che stanno per caricare file in un REPL.

Quindi ecco la mia domanda: tutte le risorse per una buona informazione o tutorial su tutto il processo di creazione di un'applicazione Clojure, tra cui la distribuzione?

(Nota: ho tutti i prerequisiti installati e di lavoro (ad esempio Emacs, Slime, Leiningen, ecc), quindi questa non è una domanda a tale proposito).

È stato utile?

Soluzione

Un paio di suggerimenti rapidi, poi alcuni link:

Non utilizzare lein uberjar durante lo sviluppo; preferiscono lein jar. La differenza è che mette lein uberjar tutte le dipendenze del jar generato (compresi Clojure stessa), in modo che il singolo barattolo è uno completamente autosufficiente pacchetto con l'app all'interno; lein jar stona solo il proprio codice. L'approccio uberjar ha benefici evidenti per la distribuzione, ma per lo sviluppo, si dovrebbe essere in grado di utilizzare solo il classpath appropriata quando si esegue la vostra applicazione, risparmiando il tempo necessario per preparare un uberjar. Se non si desidera a portata di mano-gestire il classpath per corse di prova, controlla la lein run plug .

Inoltre, molto probabilmente la maggior parte del codice non dovrebbe in realtà essere AOT compilato. AOT è necessaria negli scenari di alcuni Java interoperabilità, ma la maggior parte del tempo che porta una leggera spinta in velocità di avvio e fastidiosi problemi con la compatibilità binaria con diverse versioni di Clojure. Suppongo che il secondo problema non è rilevante per un uberjar-ed autonomo app tipo di progetto, ma qualsiasi codice della libreria almeno dovrebbe essere lasciato ad essere JIT-ed, se possibile. Con Leiningen, si può mettere una clausola :namespaces nella forma defproject in project.clj per determinare quali spazi dei nomi devono essere elaborate; tutto ciò che si lascia fuori sarà essere attualmente JIT-ed per impostazione predefinita. Le vecchie versioni di Leiningen utilizzati per compilare tutto di default, che in realtà è un buon motivo per aggiornare!

Per quanto riguarda le finestre saltar fuori durante la compilazione, direi che si sta correndo o finestra-out-popping code durante il tempo di espansione macro o al di fuori di qualsiasi definizione di funzione o costrutto simile. (Qualcosa come un (println "Foo!") al livello più alto.) Questo è solo qualcosa che non si dovrebbe fare, suppongo - a meno che non si prevede di eseguire il codice come uno script, in ogni caso. Per evitare il problema, impacco laterale effettuando codice in definizioni di funzioni e di fornire un punto di ingresso per l'applicazione utilizzando la clausola :main in project.clj. (Se dici :main foo, allora la funzione -main dallo spazio dei nomi foo sarà usato come punto di ingresso per la vostra applicazione Questo è il default, in ogni caso, e almeno quanto sopra lein run menzionata sembra avere il nome hardcoded -. Non sono sicuro di Lein stesso.)

Per quanto riguarda il ripristino dello stato del REPL - si può semplicemente riavviarlo. Di melma, M-x melma-restart-inferiore-lisp farà proprio questo, pur mantenendo tutti gli altri lo stato della sessione di Emacs.

Vedi anche queste discussioni sul gruppo Clojure Google:

  1. Clojure per l'amministrazione del sistema
  2. Prepping clojure per il confezionamento (era: Re: Clojure per l'amministrazione del sistema)
  3. Leiningen, Clojure e biblioteche: Che cosa mi manca

Altri suggerimenti

No, non entrare funzioni sul REPL.

Si modifica i file di origine, come al solito. Il vantaggio Lisp è che avete il sistema in esecuzione in background, allo stesso tempo, in modo da poter compilare singole funzioni dal file di origine e metterli nel sistema in esecuzione, o addirittura sostituirli lì.

Se si utilizza Slime, si preme C-c C-c nel file sorgente per compilare e caricare la funzione al punto. È quindi possibile passare alla REPL alla prova ed esplorare, ma tutto quello che vuoi a persistere come sorgente, si mette nei file di origine.

Esercitazioni di solito inizia dalle cose digitando sul REPL, perché non c'è molto è necessario impostare per questo, ma lo sviluppo serio integra il sistema e la fonte di gestione dei file in esecuzione.


Proprio per illustrare, il mio solito flusso di lavoro (sto usando Common Lisp, ma Clojure è simile) è in questo modo:

  • Avvia Emacs
  • M-x slime per avviare Slime, il sistema Lisp, e collegare i due tramite Swank
  • , (comando) load-system foo per caricare il progetto corrente (compilazione solo se necessario) nell'immagine
  • interruttore C-x b ad un buffer di origine
  • C-c ~ rendere la directory di origine nella directory corrente e il pacchetto sorgente del pacchetto attuale del REPL

Ora, sto istituito con il mio sistema in esecuzione in background. Di lavoro è quindi:

  • modificare o aggiungere una definizione di funzione o di classe
  • C-c C-c compilare e caricarlo nell'immagine
  • interruttore per REPL, test
  • debug

Non ci sono significative pause di compilazione, perché non ho mai compilo il tutto in una sola volta, solo singole definizioni.

scroll top