È possibile dividere uno spazio dei nomi Clojure su più file di origine quando si esegue la compilazione anticipata con :gen-class
? Come fare (:main true)
e (defn- ...)
entrare in gioco?
Risposte:
Certamente puoi, infatti lo clojure.core
stesso spazio dei nomi è suddiviso in questo modo e fornisce un buon modello che puoi seguire guardando in src/clj/clojure
:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
Tutti questi file partecipano alla costruzione del singolo clojure.core
spazio dei nomi.
Uno di questi è il file principale, denominato in modo che corrisponda al nome dello spazio dei nomi in modo che venga trovato quando qualcuno lo menziona in :use
o :require
. In questo caso il file principale è clojure/core.clj
, e inizia con un ns
modulo. Qui è dove dovresti mettere tutta la configurazione dello spazio dei nomi, indipendentemente da quale degli altri tuoi file potrebbe averne bisogno. Questo normalmente include :gen-class
anche, quindi qualcosa come:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
Quindi nei punti appropriati nel tuo file principale (più comunemente tutti alla fine) usa load
per portare i tuoi file di supporto. In clojure.core
sembra questo:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
Nota che non hai bisogno della directory corrente come prefisso, né hai bisogno del .clj
suffisso.
Ciascuno dei file di supporto dovrebbe iniziare dichiarando quale spazio dei nomi sta aiutando, ma dovrebbe farlo usando la in-ns
funzione. Quindi, per lo spazio dei nomi di esempio sopra, i file helper inizierebbero tutti con:
(in-ns 'my.lib.of.excellence)
È tutto ciò che serve.
Poiché tutti questi file creano un unico spazio dei nomi, ogni funzione definita può trovarsi in uno qualsiasi dei file principali o di supporto. Questo ovviamente significa che puoi definire le tue gen-class
funzioni in qualsiasi file desideri:
(defn -main [& args]
...)
Nota che le normali regole dell'ordine di definizione di Clojure si applicano ancora a tutte le funzioni, quindi devi assicurarti che qualunque file definisce una funzione sia caricato prima di provare a usare quella funzione.
Hai anche chiesto informazioni sul (defn- foo ...)
modulo che definisce una funzione privata dello spazio dei nomi. Le funzioni definite in questo modo e altre :private
variabili sono visibili dall'interno dello spazio dei nomi in cui sono definite, quindi i file primari e tutti gli helper avranno accesso alle variabili private definite in uno qualsiasi dei file caricati finora.