🦀

Rustの勉強 7日目

2022/10/03に公開

The Rust Programming Language 日本語版 第7章

7.1 パッケージとクレート

  • クレートにはバイナリとライブラリの2種類がある
  • パッケージは Cargo.toml でビルド方法に関する情報を保持
  • cargo new で新規パッケージを作成
    • src/main.rs はパッケージ名と同名のバイナリクレートのルート
    • src/lib.rs はパッケージ名と同名のライブラリクレートのルート

7.2 モジュールを定義して、スコープとプライバシーを制御する

  • ライブラリパッケージを作る場合 cargo new --lib で出来る
  • モジュールはクレート内のコードをグループ化する。プライバシーの制御もする。
  • mod キーワードでモジュールのスコープを作成する
    • モジュールはネストできる
  • モジュールはツリー構造で管理される
    • 一番の親は必ず crate というクレートとなる

7.3 モジュールツリーの要素を示すためのパス

  • モジュールパスは相対パスでも絶対パスでも :: の区切りで表す
    • 絶対と相対の表し方はファイルパスと似ている
    • 親モジュールの相対パスは super で始めればよい(ファイルパスで言うところの ..
  • あらゆる要素はデフォルトではプライベート
    • 親は子モジュールの要素は原則プライベートで使えない
    • 子は親モジュールの要素を使える
  • pub キーワードを使うことで外部に公開できる
    • モジュール名に pub を付けても中身が公開されるわけではない
    • 公開する要素ごとに pub を付けないといけない
    • 公開する要素というのは各構造体のフィールドも含む(Goでもフィールドごとに大文字・小文字で公開非公開を分けているので同様)
    • Enum型の場合は enum キーワードの前に pub を置くだけで全列挙子が公開される(されないと困るので直感的)

7.4 useキーワードでパスをスコープに持ち込む

  • use キーワードを使うといちいち相対パスや絶対パスでモジュールを使わなくて済む
  • 関数を呼ぶ場合は慣例では公開されているモジュールを use して、 モジュール名::関数名 で呼ぶ
    • 直接関数を use してしまうと分かりづらい
  • データ型を呼ぶ場合はフルパスを use で指定する
    • データ型にはメソッドなどがあるのでモジュールまでとすると記述量が長くなってしまう
  • 同じ名前の型を同じモジュールで使う場合には親モジュール名を指定しなければいけない
    • as キーワードを使うとエイリアスを与えることが出来、これで名前の衝突を避けられる
use std::fmt;
use std::io;

fn function1() -> fmt::Result { ... }
fn function2() -> io::Result { ... }
  • pub use を使うと、自分たちが use したモジュールをそのままの形で公開できる
  • 同じ親を持つ複数のモジュールを波カッコで囲ってまとめて use できる
  • また glob を使ってまとめて取り込むことも出来る
use std::{cmp::Ordering, io};
use std::io::{self, Write};
use std::collections::*;

7.5 モジュールを複数のファイルに分割する

  • ブロックを作らずに mod モジュール名; という文を書くと、モジュール名と同名のファイルやディレクトリから中身を引っ張ってくる

Rustlings

modules が第7章に相当するのでやってみる

modules1.rs

sausage_factory モジュール自体とその中の make_sausage 関数はプライベートなので、pub を使って公開する

pub mod sausage_factory {
    // Don't let anybody outside of this module see this!
    fn get_secret_recipe() -> String {
        String::from("Ginger")
    }

    pub fn make_sausage() {
        get_secret_recipe();
        println!("sausage!");
    }
}

fn main() {
    sausage_factory::make_sausage();
}

modules2.rs

fruitsveggies の中の const の宣言方法はよくわからないけど、 println! の中で参照されているものが存在しないので、エイリアスとして定義した。

pub mod delicious_snacks {
    pub use self::fruits::PEAR as fruit;
    pub use self::veggies::CUCUMBER as veggie;

    mod fruits {
        pub const PEAR: &'static str = "Pear";
        pub const APPLE: &'static str = "Apple";
    }

    mod veggies {
        pub const CUCUMBER: &'static str = "Cucumber";
        pub const CARROT: &'static str = "Carrot";
    }
}

fn main() {
    println!(
        "favorite snacks: {} and {}",
        delicious_snacks::fruit,
        delicious_snacks::veggie
    );
}

modules3.rs

問題のコメントに std::time モジュールにあるよ、って書いてあったので、まとめて use した。

use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    match SystemTime::now().duration_since(UNIX_EPOCH) {
        Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    }
}

Discussion