Можно ли разделить пространство имен Clojure на несколько исходных файлов при выполнении компиляции со временем :gen-class
? Как вступают в игру (:main true)
и (defn- ...)
?
Разделение пространства имен Clojure на несколько файлов
Ответ 1
Обзор
Конечно, вы можете, фактически, пространство имен clojure.core
разбито таким образом и предоставляет хорошую модель, за которой вы можете следовать, глядя в src/clj/clojure
:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
Все эти файлы участвуют в создании единого пространства имен clojure.core
.
Основной файл
Один из них - это первичный файл, названный так, чтобы соответствовать имени пространства имен, чтобы он был найден, когда кто-то упоминает его в :use
или :require
. В этом случае основной файл clojure/core.clj
, и он начинается с формы ns
. Здесь вы должны поместить всю свою конфигурацию пространства имен, независимо от того, какой из ваших других файлов может понадобиться. Обычно это также :gen-class
, поэтому что-то вроде:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
Затем в соответствующих местах вашего основного файла (чаще всего все в конце) используйте load
для ввода ваших вспомогательных файлов. В clojure.core
это выглядит так:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
Обратите внимание, что вам не нужен текущий каталог в качестве префикса, и вам не нужен суффикс .clj
.
Файлы-помощники
Каждый из вспомогательных файлов должен начинаться с объявления того пространства имён, которое им нужно, но должен делать это с помощью функции in-ns
. Итак, для примера пространства имен выше, хелпер файлы будут начинаться с:
(in-ns 'my.lib.of.excellence)
Это все, что требуется.
генераторного класса
Поскольку все эти файлы создают единое пространство имен, каждая определяемая вами функция может быть в любом из первичных или вспомогательных файлов. Это, конечно, означает, что вы можете определить свои функции gen-class
в любом файле, который вы хотите:
(defn -main [& args]
...)
Обратите внимание, что для всех функций все еще применяются правила стандартного порядка определения Clojure, поэтому перед попыткой использовать эту функцию необходимо убедиться, что какой-либо файл определяет функцию.
Частные войны
Вы также спросили о форме (defn- foo ...)
, которая определяет частную функцию namespace-private. Функции, определенные таким образом, а также другие :private
vars видны из пространства имен, где они определены, поэтому основной и все вспомогательные файлы будут иметь доступ к приватным vars, определенным в любом из файлов, загруженных до сих пор.