web-dev-qa-db-fra.com

Fractionnement d'un espace de noms Clojure sur plusieurs fichiers

Est-il possible de diviser un espace de noms Clojure sur plusieurs fichiers source lors de la compilation anticipée avec :gen-class? Comment faire (:main true) et (defn- ...) entrer en jeu?

89
Ralph

Aperçu

Vous pouvez certainement, en fait clojure.core l'espace de noms lui-même est divisé de cette façon et fournit un bon modèle que vous pouvez suivre en regardant dans src/clj/clojure:

core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..

Tous ces fichiers participent à la construction du seul clojure.core espace de noms.

Fichier principal

L'un d'entre eux est le fichier principal, nommé pour correspondre au nom de l'espace de noms afin qu'il soit trouvé lorsque quelqu'un le mentionne dans un :use ou :require. Dans ce cas, le fichier principal est clojure/core.clj, et il commence par une forme ns. C'est là que vous devez mettre all la configuration de votre espace de noms, quels que soient vos autres fichiers qui en ont besoin. Cela inclut normalement :gen-class aussi, donc quelque chose comme:

(ns my.lib.of.excellence
  (:use [clojure.Java.io :as io :only [reader]])
  (:gen-class :main true))

Ensuite, aux endroits appropriés dans votre fichier principal (le plus souvent à la fin), utilisez load pour importer vos fichiers d'assistance. Dans clojure.core cela ressemble à ceci:

(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")

Notez que vous n'avez pas besoin du répertoire actuel comme préfixe, ni de .clj suffixe.

Fichiers d'aide

Chacun des fichiers d'assistance doit commencer par déclarer l'espace de noms qu'il aide, mais doit le faire en utilisant le in-ns fonction. Ainsi, pour l'exemple d'espace de noms ci-dessus, les fichiers d'assistance commenceraient tous par:

(in-ns 'my.lib.of.excellence)

C'est tout ce qu'il faut.

classe gen

Étant donné que tous ces fichiers créent un espace de noms unique, chaque fonction que vous définissez peut se trouver dans l'un des fichiers principaux ou auxiliaires. Cela signifie bien sûr que vous pouvez définir votre gen-class fonctionne dans n'importe quel fichier que vous souhaitez:

(defn -main [& args]
  ...)

Notez que les règles normales d'ordre de définition de Clojure s'appliquent toujours à toutes les fonctions, vous devez donc vous assurer que quel que soit le fichier définit une fonction est chargé avant d'essayer de tiliser que fonction.

Vars privé

Vous avez également posé une question sur le (defn- foo ...) formulaire qui définit une fonction d'espace de noms privé. Fonctions définies comme ceci ainsi que d'autres :private les variables sont visibles depuis l'espace de noms où elles sont définies, de sorte que les fichiers principaux et tous les fichiers auxiliaires auront accès aux variables privées définies dans l'un des fichiers chargés jusqu'à présent.

135
Chouser