20250823145330 rustのモジュール(mod) について

rust

modは私の理解ではC++のnamespaceに近い。 rustのnamespaceの詳細はこちらを参照: Namespaces - The Rust Reference

main.rsしかない単一のソースの場合

mod でかこった識別子がnamespace的に使える。公開/非公開が設定できる点はnamespaceより優れている。

// トップレベルのmodはpubつけなくても見える
mod hoge { 
    // 公開する要素はpubをつける
    pub fn hoge_function() {
        println!("hoge");
    }
 
    // 公開しない要素はpubをつけない
    fn fuga_function() {
        println!("fuga");
    }
    // ネストしたmodは、pubをつけないと見えない
    pub mod nested_hoge {
        // ネストしたmodの中の要素も、pubをつけないと見えない
        pub fn nested_hoge_function() {
            println!("nested_hoge");
        }
 
    }
}
// トップレベルの関数はpubをつけなくても見える
fn naked_function() {
    println!("naked");
}
fn main()
{
    naked_function();
    hoge::hoge_function();
    hoge::nested_hoge::nested_hoge_function();
    //hoge::fuga_function(); // コンパイルエラーになる
}
別ソースの関数を呼ぶ場合 その1

ファイル名が自動的にnamespace的なものの1つとして追加される。

another.rs

pub fn another_function() {
    println!("another");
}
 
// ここのmodはpubが必要
pub mod inner {
    pub fn inner_function() {
        println!("inner");
    }
}

main.rs

// another.rsをモジュールとして取り込む記法。ファイル名から.rsを除いたものが自動的にモジュール名になる。
mod another; 
 
fn main()
{
    another::another_function();
    another::inner::inner_function();
 
    // useを使うと、毎回モジュール名を書く必要がなくなる
    use another::inner::inner_function;
    inner_function();
}
 
fn main()
{
    another::another_function();
    another::inner::inner_function();
 
    // useを使うと、毎回モジュール名を書く必要がなくなる
    use another::inner::inner_function;
    inner_function();
 
    // useの範囲は色々にできる
    use another::inner;
    inner::inner_function(); // C++の using namespaceと微妙に違っていて、::の最後の部分は省略できないようだ。
}
 
別ソースの関数を呼ぶ場合 その2

サブディレクトリがある場合

./dir/file_in_dir.rs

pub fn file_in_dir_function() {
    println!("file_in_dir");
}

./dir.rs (このファイルが無いとサブディレクトリは認識されない。ここに個人的には若干違和感がある)

pub mod file_in_dir;

main.rs

mod dir;
fn main()
{
    dir::file_in_dir::file_in_dir_function();
}
 
crate::

裸の関数とみせかけてcrateというのがルートのmodとして定義されている。

fn naked() {
    println!("naked");
}
// mainも crate::mainと定義される
fn main() {
    crate::naked();
}
ルートファイル(main.rs, lib.rs) 以外のファイル同士で相互に関数を呼ぶ

この場合に前述の crate:: が必要になる。

./file1.rs

pub fn file_1_function() {
    println!("file_1");
    
    crate::file_2::file_2_function(); //このように crate:: が必要
    super::file_2::file_2_function(); // super で1階層上(=この場合crate) にアクセスすることも可能。
}

./file2.rs

pub fn file_2_function() {
    println!("file_2");
}

main.rs

mod file_1;
mod file_2; // ルートファイルに必要なmodを記載する必要がある!ここはつまづきポイントだと思う
 
fn main() {
    file_1::file_1_function();
}

refs.