namespaces - Dividir un espacio de nombre Clojure en varios archivos
compilation (1)
Visión de conjunto
Ciertamente usted puede, de hecho, el espacio de nombres clojure.core
mismo se divide de esta manera y proporciona un buen modelo que puede seguir buscando en src/clj/clojure
:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
Todos estos archivos participan para crear el espacio de nombres único clojure.core
.
Archivo principal
Uno de estos es el archivo principal, cuyo nombre coincide con el nombre del espacio de nombres para que se encuentre cuando alguien lo menciona en a :use
o :require
. En este caso, el archivo principal es clojure/core.clj
, y comienza con un formulario ns
. Aquí es donde debe colocar toda su configuración de espacio de nombres, independientemente de cuáles de sus otros archivos puedan necesitarlos. Esto normalmente incluye :gen-class
también, algo así como:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
Luego, en los lugares apropiados en su archivo primario (más comúnmente al final) use load
para traer sus archivos auxiliares. En clojure.core
se ve así:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
Tenga en cuenta que no necesita el directorio actual como prefijo, ni necesita el sufijo .clj
.
Archivos de ayuda
Cada uno de los archivos auxiliares debe comenzar por declarar qué espacio de nombres están ayudando, pero debe hacerlo utilizando la función in-ns
. Entonces, para el espacio de nombres de ejemplo anterior, los archivos auxiliares comenzarían todos con:
(in-ns ''my.lib.of.excellence)
Eso es todo lo que se necesita.
gen-class
Debido a que todos estos archivos están creando un solo espacio de nombres, cada función que defina puede estar en cualquiera de los archivos primarios o auxiliares. Esto, por supuesto, significa que puede definir sus funciones gen-class
en cualquier archivo que desee:
(defn -main [& args]
...)
Tenga en cuenta que las reglas de orden de definición normales de Clojure aún se aplican a todas las funciones, por lo que debe asegurarse de que cualquier archivo que define una función se cargue antes de intentar usar esa función.
Vars Privados
También preguntaste sobre el (defn- foo ...)
que define una función privada del espacio de nombres. Funciones definidas de la siguiente manera :private
vars :private
son visibles desde el espacio de nombres donde están definidos, por lo que los archivos primarios y todos los helper tendrán acceso a vars privados definidos en cualquiera de los archivos cargados hasta el momento.
¿Es posible dividir un espacio de nombres de Clojure sobre varios archivos de origen al hacer una compilación anticipada con :gen-class
? ¿Cómo (defn- ...)
(:main true)
y (defn- ...)
entran en juego?