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.core
sama 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.core
przestrzeni 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 :use
lub :require
. W tym przypadku głównym plikiem jest clojure/core.clj
i zaczyna się od ns
formularza. 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-class
ró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, load
aby wprowadzić pliki pomocnicze. W clojure.core
tym 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 .clj
sufiksu.
Każdy z plików pomocniczych powinien zaczynać się od zadeklarowania, której przestrzeni nazw pomaga, ale powinien to zrobić za pomocą in-ns
funkcji. 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-class
funkcje 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 :private
zmienne, 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.