É possível dividir um namespace Clojure em vários arquivos de origem ao fazer uma compilação antecipada com :gen-class
? Como fazer (:main true)
e (defn- ...)
entram em jogo?
fonte
É possível dividir um namespace Clojure em vários arquivos de origem ao fazer uma compilação antecipada com :gen-class
? Como fazer (:main true)
e (defn- ...)
entram em jogo?
Certamente você pode; na verdade, o clojure.core
próprio namespace é dividido dessa maneira e fornece um bom modelo que você pode seguir observando src/clj/clojure
:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
Todos esses arquivos participam para construir o clojure.core
namespace único .
Um deles é o arquivo principal, nomeado para corresponder ao nome do namespace para que seja encontrado quando alguém mencioná-lo em um :use
ou :require
. Neste caso, o arquivo principal é clojure/core.clj
e começa com um ns
formulário. É aqui que você deve colocar toda a configuração do seu namespace, independentemente de quais dos outros arquivos possam precisar deles. Isso normalmente inclui :gen-class
também, algo como:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
Em seguida, em locais apropriados em seu arquivo principal (mais comumente todos no final), use load
para trazer seus arquivos auxiliares. Nele clojure.core
se parece com isto:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
Observe que você não precisa do diretório atual como prefixo, nem precisa do .clj
sufixo.
Cada um dos arquivos auxiliares deve começar declarando qual namespace está ajudando, mas deve fazer isso usando a in-ns
função. Portanto, para o exemplo de namespace acima, todos os arquivos auxiliares começariam com:
(in-ns 'my.lib.of.excellence)
Isso é tudo o que preciso.
Como todos esses arquivos estão construindo um único namespace, cada função que você define pode estar em qualquer um dos arquivos primários ou auxiliares. Isso significa que você pode definir suas gen-class
funções em qualquer arquivo que desejar:
(defn -main [& args]
...)
Observe que as regras de ordem de definição normais do Clojure ainda se aplicam a todas as funções, portanto, você precisa se certificar de que qualquer arquivo que defina uma função seja carregado antes de tentar usar essa função.
Você também perguntou sobre o (defn- foo ...)
formulário que define uma função privada de namespace. Funções definidas assim, bem como outras :private
vars, são visíveis de dentro do namespace onde estão definidas, então o primário e todos os arquivos auxiliares terão acesso a vars privados definidos em qualquer um dos arquivos carregados até agora.