Rustは、モジュールシステムも色々決まりがあって整っているので、単にファイルを分けて書こうと思った場合にも、整った綺麗な書き方をするには難しい言語に感じます。
自分も、丁度Rustでプログラムを書いていた時に迷って良いリポジトリから良い書き方を見つけたのでその紹介をしようと思います。
情報が少ない!
Rustのファイル分割は、情報を探そうとしても自分はなかなか出てきませんでした。英語で検索かけても、まとまったページがなかったのでここにまとめておきます。
参考にしたリポジトリ
GitHub - maekawatoshiki/naglfar: A toy web browser implemented in Rust from scratch
これですね、Rustで色々書いてる人のリポジトリを参考にしました。
せっかちな人向けに最初に方法を
Rustは~~cargo test
ではlib.rs
が実行され~~、cargo run
でmain.rs
が実行されるようです。
Jul 20 訂正
cargo test
は同クレート内のファイルを見渡して#[test]
が在る部分が実行されます。
main.rsには
/* main.rs */
extern crate クレート名;
fn main() {
/* process ... */
}
こんな風に書きます。
そして、
lib.rsには
/* lib.rs */
/* A */
pub mod structs;
pub mod token;
pub mod monominal;
pub mod expression;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
ここでコード内Aの場所でpub modしてますが、pub modで指定したモジュール名に.rsをつけたファイルが自動的に読み込まれます。
なので、この上の例ではディレクトリ構造は以下のようになっているはずです。
. (クレート名)
├── Cargo.lock
├── Cargo.toml
└── src
├── main.rs
├── lib.rs
├── structs.rs
├── token.rs
├── monominal.rs
└── expression.rs
/* token.rs */
use structs::*;
/* ... */
lib.rsにpub modされているファイルの1つ(token.rs)を見てみましょう。ここではstructs.rsの内容が必要なようです。このようなときにはuseを使いましょう。
まとめると、
Rustでファイル分割
- main.rsでは(クレートを使うときは)extern crate クレート名を書いてモジュールを読み込める(必須ではない
- lib.rsではpub mod モジュール名を使って公開するモジュールを指定する(公開したくなかったらpub抜いて)
- モジュール名.rs内で他のモジュールを使いたい場合はuse モジュール名でどうぞ
内部の仕組みとか交えつつ説明
Rustのモジュールは色々管理されていて、他の言語から来た人には窮屈に感じることが在るかもしれません。
extern crate
これを使えば外部のクレートをインポートすることができます。
[pub] mod
これはモジュールを宣言することができます。他のファイル(モジュール名.rs
かモジュール名/mod.rs
)を探しに行って読み込むことができます。pubを使うとそのモジュールを公開します。
例えばlib.rsにpubを付けないとmain.rsなど、そのクレートを使うスクリプトからextern crateで読み込んだ時に、内部のそのモジュールにアクセスできなくなります。
use
名前を短くするのに使うことができます。
例えば、main.rsで
/* main.rs */
extern crate kokmath;
kokmath::structs::Token::Scalar(3.);
と書かないといけないところを簡単に
/* main.rs */
extern crate kokmath;
use kokmath::structs; // kokmath::structsをstructsと書くだけで良い
structs::Token::Scalar(3.);
と書いたり、
/* main.rs */
extern crate kokmath;
use kokmath::structs::*; // kokmath::structs::何か を 何か と書くだけで良い
Token::Scalar(3.);
と書いたりすることが出来るわけです。
pub use
これはちょっと複雑ですが、簡単に言うと構造を変えることができます。
例えば、さっきのmain.rsでkokmath::structs::TokenとやってTokenにアクセスしていましたが、これはuseでどうやっても、kokmath::Tokenとやってアクセスするように変更することはできません。
lib.rsを見れば分かるようにTokenはstructsの中にあって、それはpub mod structsで読み込まれていますので、これを実現するためにはkokmathのコードを改変する必要があります。なんとか、lib.rsでなんとかできないのか。こんな時にこれが使えて、
/* lib.rs */
pub mod structs;
pub mod token;
pub mod monominal;
pub mod expression;
pub use structs::*; // ここ! ここでstructsの中身を全て引き出して、「その結果を公開してこれを読み込むクレートに適用させる」
...
と書き換えることで、main.rsで
/* main.rs */
extern crate kokmath;
kokmath::Token::Scalar(3.);
とすることができます😊
まとめ
Rustでファイル分割
- main.rsでは(クレートを使うときは)extern crate クレート名を書いてモジュールを読み込める(必須ではない
- lib.rsではpub mod モジュール名を使って公開するモジュールを指定する(公開したくなかったらpub抜いて)
- モジュール名.rs内で他のモジュールを使いたい場合はuse モジュール名でどうぞ