Clojure名前空間を複数のファイルに分割する


91

で事前コンパイルを行うときに、Clojure名前空間を複数のソースファイルに分割することは可能:gen-classですか?どのように(:main true)して(defn- ...)遊びに来ますか?

回答:


137

概観

確かにできます。実際、clojure.core名前空間自体はこのように分割されており、次の場所を調べることで従うことができる優れたモデルを提供しますsrc/clj/clojure

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

これらすべてのファイルが参加して、単一のclojure.core名前空間を構築します。

プライマリファイル

これらの1つは、名前空間名と一致するように名前が付けられたプライマリファイルで、誰かが: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

これらのすべてのファイルが単一の名前空間を構築しているため、定義する各関数は、プライマリファイルまたはヘルパーファイルのいずれかに置くことができます。もちろん、これはgen-class、任意のファイルで関数を定義できることを意味します。

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

Clojureの通常の定義順序規則は引き続きすべての関数に適用されることに注意してください。そのため、その関数を使用する前に、関数を定義するファイルがロードされていることを確認する必要があります。

プライベートVars

(defn- foo ...)名前空間プライベート関数を定義するフォームについても質問しました。このように定義された関数と他の:private変数は、それらが定義されているネームスペース内から表示できるため、プライマリおよびすべてのヘルパーファイルは、これまでに読み込まれたファイルで定義されたプライベート変数にアクセスできます。


3
とても良い、完全な答え!ところで、私はThe Joy of Clojureの最初のパスでほぼ終了しています。素晴らしい本!
ラルフ

この答えを共有してくれてありがとう。2年後も、それは良い習慣と見なされていますか?(状況は急速に変化します。)Clojure自体がまだこの手法を使用していることがわかります。
David J.

9
今日でも、複数のファイルで単一の名前空間を生成することが確実である場合、これは依然としてベストプラクティスです。しかし、それ自体は今では以前ほど一般的ではないかもしれません。別の方法として、nsのすべてのパブリック変数を1つのファイルで定義し、すべてのヘルパー変数と関数を別の「実装」名前空間に移動することもできます。implの変数は技術的には公開されますが、ドキュメント化されたAPIの一部ではないことを示すns docstringは一般的であり、十分なはずです。
Chouser 2013年

1
一般的なClojureツールでマルチファイル名前空間の理解に問題があるかどうかを知っていますか?レイン?ブート?サイダー?nREPL?キビット?イーストウッド?クローバー?その他...
Didier A.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.