やっつけな日常(30) Rustに入ればRustに従え、モジュールを別ファイルにするお作法

Joseph Halfmoon

時折Rust言語を使ってみては、慣れぬRustのお作法に行く手を阻まれます。今回は、関数やらモジュールやらを別ファイル(ついでに別階層)にして取り込む件。Cのようにヘッダファイルを作ったり、Makefile書いたりする必要ないですが、初心者にはあまり親切ではない気がします。やれば出来る?ホントか。

今回は真っ先に以下の「偉大なコメント」を引用させていただきたいと思います。これひとつでスッキリ? いつもお世話になっております「Rust By Example 日本語版」の以下のページからの引用でございます。

ファイルの階層構造

“mod my;” という短い1行に対するコメントなんであります。MY

なんだ、そういうことかい。

「パッケージとクレート」読んでました

最初、パッケージとクレートについて調べ始めて沼にハマりました。Rustには素晴らしいモジュール管理システムが備わってます。パッケージとクレートについても理解しないとイケないのだと思いますが、今回やりたかったのは、「main.rs内で定義している関数などを別ファイルに追い出したい」ついでによくやる風に「ローカル・ライブラリ的なフォルダを掘って別階層にまとめたい」という程度の事なんであります。とりあえず戸惑った第1歩だけ書き留めておきますが、ファイルを分けるだけならココは飛ばして大丈夫です。

Rustのプロジェクトを作る場合、Cargoに以下のようにお願いして xxx などというプロジェクトホルダを作ると思います。

cargo new xxx

上記の場合、「バイナリ」パッケージで、srcサブフォルダの中に main.rs の雛形が用意されてます。

それに対してライブラリのプロジェクトを作るときはオプション –lib つけるとsrcサブフォルダの中に lib.rs の雛形が用意されてます。

cargo new yyy --lib

そして上記の2つは両立しない、ようです。ライブラリ・プロジェクトの作り方を調べても的外れだったみたいです。

Rustにはクレートという概念があり、クレートルートというものを開始点に組織化されてます。そこで

    1. クレートにはバイナリとライブラリの種別がある
    2. パッケージは最低一つのクレートを持たねばならない
    3. パッケージが持てるライブラリ・クレートは0または1個
    4. パッケージが持てるバイナリ・クレートの数に制限はない

なんやら複雑な。。。そしてこの辺を読んでいても現状目的とする方向へは進まず、深みにズブズブとクレートなるものにハマって行きます。その辺はまた今度。

まずは単一ファイル内でのモジュール内関数の呼び出しから

まずは、main.rs内で、簡単なモジュールを定義してその中の関数を呼んでみるところから。こんな感じ。mainRS

普通に cargo run などとすれば、ビルドされて走ります。実行後のプロジェクト・フォルダのツリー(一部)は以下のようです。AfterRun

同一階層でファイルを分けてみる

同一階層でファイルを2つに分割してみました。ソースの階層構造が以下に。sameLevel

ここで main.rs のコードが以下に。slMain

これに対する、trial.rs は以下です。slSub

 

同一ファイルの時には、sub1をmod{ } で囲っていたのに削除してます。これは main.rs内で、mod trial; と宣言したときに既に mod にくるまれているためです。trial.rsファイル内に modを書くと、二重になってしまい、::trial::trial::sub1みたいな長いパスで呼ばねばならないなります。

階層構造にする

ここから階層構造にするのは簡単です。

    1. trial.rs をmod.rsとリネーム
    2. trialという名のサブフォルダを掘って
    3. mod.rs をtrialサブフォルダにMOVE

mod.rsとか「マジックな」ファイル名を知っていたら簡単でしたな。

しかしこれだけではツマラナイので、さらにネストしたモジュール・ファイルを置いてこれも参照できるようにしてみました。階層構造が以下に。trial2Tree

 

 

追加した nested2.rs の中身が以下です。超シンプルなモジュール。モジュールも関数も皆パブリック。trial2

そして mod.rs 内に以下一行を付け加えました。

pub mod nested2;

すると main.rs からは以下のように trial経由のnested2経由のtrial2モジュール内のsub2という長いお名前でアクセスできました。

 trial::nested2::trial2::sub2();

全部合わせた実行結果が以下に。

Results

たったこんだけ、でもま、会得したような気がする。気のせいじゃないのか自分?

やっつけな日常(29) Rustに入ればRustに従え、「所有権」を「借用」できたのね へ戻る

やっつけな日常(31) Rustに入ればRustに従え、お名前のお作法、いろいろあるのよ へ進む