75
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rustでファイル分割

Last updated at Posted at 2018-07-19

元記事 - https://cretgp.com/blog/20180719%20Rust%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%88%86%E5%89%B2.html

Rustは、モジュールシステムも色々決まりがあって整っているので、単にファイルを分けて書こうと思った場合にも、整った綺麗な書き方をするには難しい言語に感じます。

自分も、丁度Rustでプログラムを書いていた時に迷って良いリポジトリから良い書き方を見つけたのでその紹介をしようと思います。

情報が少ない!

Rustのファイル分割は、情報を探そうとしても自分はなかなか出てきませんでした。英語で検索かけても、まとまったページがなかったのでここにまとめておきます。

参考にしたリポジトリ

GitHub - maekawatoshiki/naglfar: A toy web browser implemented in Rust from scratch

これですね、Rustで色々書いてる人のリポジトリを参考にしました。

せっかちな人向けに最初に方法を

Rustは~~cargo testではlib.rsが実行され~~、cargo runmain.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でファイル分割

  1. main.rsでは(クレートを使うときは)extern crate クレート名を書いてモジュールを読み込める(必須ではない
  2. lib.rsではpub mod モジュール名を使って公開するモジュールを指定する(公開したくなかったらpub抜いて)
  3. モジュール名.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でファイル分割

  1. main.rsでは(クレートを使うときは)extern crate クレート名を書いてモジュールを読み込める(必須ではない
  2. lib.rsではpub mod モジュール名を使って公開するモジュールを指定する(公開したくなかったらpub抜いて)
  3. モジュール名.rs内で他のモジュールを使いたい場合はuse モジュール名でどうぞ
75
39
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
75
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?