ファイルの読み込み¶
小さなコード片やベンチマークコードであれば、単一のファイルにプログラムを記述しても問題ありません。しかし、大規模なプログラムは、複数のファイルに分割することで、保守性と理解度が向上します。
コンパイラに他のファイルを処理させるには、`require "..."` を使用します。これは、文字列リテラルである単一の引数を受け取り、様々な形式で記述できます。
ファイルが一度読み込まれると、コンパイラはその絶対パスを記憶し、後で同じファイルに対する `require` は無視されます。
require "filename"¶
これは、読み込みパス内で "filename" を検索します。
デフォルトでは、読み込みパスには2つの場所が含まれています。
- 現在の作業ディレクトリからの相対パスで `lib` ディレクトリ (依存関係が検索される場所です)
- コンパイラに付属する標準ライブラリの場所
これらだけが検索される場所です.
コンパイラが使用する正確なパスは `crystal env CRYSTAL_PATH` でクエリできます。
$ crystal env CRYSTAL_PATH
lib:/usr/bin/../share/crystal/src
これらの検索パスは、`CRYSTAL_PATH` 環境変数を定義することでオーバーライドできます。
検索は次のようになります。
- 読み込みパスに "filename.cr" という名前のファイルが見つかった場合、それが読み込まれます。
- "filename" という名前のディレクトリが見つかり、その直下に "filename.cr" という名前のファイルが含まれている場合、それが読み込まれます。
- "filename" という名前のディレクトリが見つかり、その中に "src" ディレクトリがあり、その直下に "filename.cr" という名前のファイルが含まれている場合、それが読み込まれます。
- それ以外の場合は、コンパイル時エラーが発生します。
2番目のルールは、次のような構造に加えて、
- project
- src
- file
- sub1.cr
- sub2.cr
- file.cr (requires "./file/*")
次のような構造も可能です。
- project
- src
- file
- file.cr (requires "./*")
- sub1.cr
- sub2.cr
これは、好みに応じて少しすっきりするかもしれません。
3番目のルールは、プロジェクトの典型的なディレクトリ構造のため非常に便利です。
- project
- lib
- foo
- src
- foo.cr
- bar
- src
- bar.cr
- src
- project.cr
- spec
- project_spec.cr
つまり、"lib/{project}" 内に各プロジェクトのディレクトリ(`src`、`spec`、`README.md` など)が存在します。
たとえば、`project.cr` に `require "foo"` を記述し、プロジェクトのルートディレクトリで `crystal src/project.cr` を実行すると、`lib/foo/foo.cr` 内の `foo` が見つかります。
4番目のルールは、3番目のルールに2番目のルールを適用したものです
コンパイラを別の場所、たとえば `src` フォルダから実行すると、`lib` はパスに含まれず、`require "foo"` は解決できません。
require "./filename"¶
これは、`require` 式を含むファイルからの相対パスで "filename" を検索します。
検索は次のようになります。
- 現在のファイルからの相対パスで "filename.cr" という名前のファイルが見つかった場合、それが読み込まれます。
- "filename" という名前のディレクトリが見つかり、その直下に "filename.cr" という名前のファイルが含まれている場合、それが読み込まれます。
- それ以外の場合は、コンパイル時エラーが発生します。
この相対パスは、主にプロジェクト内で他のファイルを参照するために使用されます。また、specsからのコードを参照するためにも使用されます
require "../src/project"
その他の形式¶
どちらの場合も、ネストされた名前を使用でき、ネストされたディレクトリ内で検索されます。
- `require "foo/bar/baz"` は、読み込みパス内で "foo/bar/baz.cr"、 "foo/bar/baz/baz.cr"、"foo/src/bar/baz.cr"、または "foo/src/bar/baz/baz.cr" を検索します。
- `require "./foo/bar/baz"` は、現在のファイルからの相対パスで "foo/bar/baz.cr" または "foo/bar/baz/baz.cr" を検索します。
また、`../` を使用して現在のファイルからの相対パスで親ディレクトリにアクセスできるため、`require "../../foo/bar"` も機能します.
これらすべての場合において、特別な `*` と `**` サフィックスを使用できます。
- `require "foo/*"` は、"foo" ディレクトリ以下のすべての ".cr" ファイルを読み込みますが、 "foo" 内のディレクトリ以下は読み込みません。
- `require "foo/**"` は、"foo" ディレクトリ以下のすべての ".cr" ファイルと、"foo" 内のディレクトリ以下のすべての ".cr" ファイルを再帰的に読み込みます。