Czy jest możliwe podzielenie przestrzeni nazw Clojure na wiele plików źródłowych podczas wykonywania kompilacji z wyprzedzeniem :gen-class? Jak zrobić (:main true)i (defn- ...)wchodzić w grę?
Odpowiedzi:
Z pewnością można, w rzeczywistości clojure.coresama przestrzeń nazw jest podzielona w ten sposób i zapewnia dobry model, który można śledzić, patrząc na src/clj/clojure:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
Wszystkie te pliki uczestniczą w tworzeniu pojedynczej clojure.coreprzestrzeni nazw.
Jednym z nich jest plik podstawowy, którego nazwa jest zgodna z nazwą przestrzeni nazw, dzięki czemu zostanie znaleziony, gdy ktoś wspomni o nim w :uselub :require. W tym przypadku głównym plikiem jest clojure/core.clji zaczyna się od nsformularza. Tutaj należy umieścić całą konfigurację przestrzeni nazw, niezależnie od tego, który z innych plików może ich potrzebować. Zwykle obejmuje to :gen-classrównież, więc coś takiego:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
Następnie w odpowiednich miejscach w pliku podstawowym (najczęściej na końcu) użyj, loadaby wprowadzić pliki pomocnicze. W clojure.coretym wygląda tak:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
Zauważ, że nie potrzebujesz bieżącego katalogu jako prefiksu, ani nie potrzebujesz .cljsufiksu.
Każdy z plików pomocniczych powinien zaczynać się od zadeklarowania, której przestrzeni nazw pomaga, ale powinien to zrobić za pomocą in-nsfunkcji. Tak więc dla powyższej przykładowej przestrzeni nazw wszystkie pliki pomocnicze zaczynałyby się od:
(in-ns 'my.lib.of.excellence)
To wszystko, czego potrzeba.
Ponieważ wszystkie te pliki tworzą jedną przestrzeń nazw, każda zdefiniowana funkcja może znajdować się w dowolnym z plików podstawowych lub pomocniczych. Oznacza to oczywiście, że możesz zdefiniować swoje gen-classfunkcje w dowolnym pliku, który chcesz:
(defn -main [& args]
...)
Zauważ, że normalne reguły kolejności definicji Clojure nadal mają zastosowanie do wszystkich funkcji, więc musisz upewnić się, że dowolny plik definiujący funkcję jest ładowany, zanim spróbujesz użyć tej funkcji.
Zapytałeś również o (defn- foo ...)formularz, który definiuje prywatną funkcję przestrzeni nazw. Funkcje zdefiniowane w ten sposób, jak również inne :privatezmienne, są widoczne z przestrzeni nazw, w której są zdefiniowane, więc podstawowe i wszystkie pliki pomocnicze będą miały dostęp do prywatnych zmiennych zdefiniowanych w dowolnym z dotychczas załadowanych plików.