2024年1月2週目のRust勉強記

概要

新たに学んだことを雑多に書いていく

学んだこと

モジュール

  • ワークスペース

    • 機能をグループにまとめられることに加え、実装の詳細がカプセル化されることにより、コードをより高いレベルで再利用できるようになる

  • モジュールシステム

    • パッケージ: クレートをビルドし、テストし、共有することができるCargoの機能

    • クレート: ライブラリか実行可能ファイルを生成する、木構造をしたモジュール群

    • モジュールuse: これを使うことで、パスの構成、スコープ、公開するか否かを決定できます

    • パス: 要素(例えば構造体や関数やモジュール)に名前をつける方法

→これは情報カードにまとめよう

  • クレート

    • バイナリクレート

      • main.rs

    • ライブラリクレート

      • lib.rs

    • どっちも持っていたら1つのパッケージにクレートが複数あることになる

  • モジュール(mod)

    • クレート内のコードをグループ化し、可読性と再利用性を上げるのに役に立つ

    • モジュールを使うことで、関連する定義を一つにまとめ、関連する理由を名前で示せる

    • 欲しい定義を見つけ出すのが簡単になる

    • モジュールはコードの整理に役立つだけではありません。 モジュールはRustの プライバシー境界 も定義します。

    • (所感)デフォルトで非公開 (private)は硬い作りで素晴らしい

    • superを使って一段上(親)のモジュールを見に行ける

  • use

    • 構造体やenumその他の要素をuseで持ち込むときは、フルパスを書くのが慣例的

pub use

  • まるでその名前が私達のコードのスコープで定義されていたかのように参照できるようにする

コレクション

  • コレクションに関するドキュメント

文字列

  • to_stringメソッド

    • Display トレイトを実装している型の値を、String 型に変換するために使われる

  • スライス

  • let hello = "Здравствуйте";

    • let s = &hello[0..4]; // OK

    • let s = &hello[0]; // NG

  • なぜ?

Rustで文字列のスライスを扱う際の問題点について、日本語で説明します。

Rustの文字列はUTF-8でエンコードされています。UTF-8では、1文字が1バイト以上を占めることがあります。例えば、"Здравствуйте"という文字列を考えてみましょう。

  1. let s = &hello[0..4]; - この行は動作します。なぜなら、文字列をバイトインデックス0からバイトインデックス4までのスライスとしています。"Здравствуйте"の最初の文字「З」は2バイトを使用します。したがって、このスライスは最初の文字とその次のバイトを含んでいます。

  2. let s = &hello[0]; - この行はエラーになります。Rustでは、文字列のインデックス操作はバイト単位で行われます。しかし、UTF-8文字列では、すべての文字が同じバイト数を占めるわけではありません。このコードは、文字列の最初のバイトだけを参照しようとしていますが、これは完全な文字を形成していません。Rustは、不完全な文字を作成することを許可しないため、この操作は無効です。

UTF-8エンコードされた文字列で安全に操作するには、文字の境界を尊重する必要があります。これは、.chars()メソッドや.char_indices()メソッドを使用して文字単位で操作することで達成できます。

エラー処理

Rustでは、エラーは大きく二つに分類されます

回復可能と回復不能なエラー

  • 回復可能なエラー: ファイルが見つからないなど。問題をユーザに報告し、処理を再試行することが合理的

    • 回復可能なエラーにはResult<T, E>値があり

  • 回復不能なエラー:常にバグの兆候です。例えば、配列の境界を超えた箇所にアクセスしようとすることなどです。

    • 実行を中止するpanic!マクロがあり

panic!

  • 標準では、パニックが発生すると、プログラムは巻き戻しを始める

  • 対立案は、即座に異常終了し、片付けをせずにプログラムを終了させる

  • バックトレース

    • RUST_BACKTRACE環境変数をセット

    • ここに至るまでに呼び出された全関数の一覧

Result

#![allow(unused)]

fn main() {

enum Result<T, E> {

Ok(T),

Err(E),

}

}

unwrap

  • unwrapはOkの中身を返す

  • ResultがErr列挙子なら、 unwrapはpanic!マクロを呼んでくれる

expect

expectを使用して、いいエラーメッセージを提供すると、意図を伝え、 パニックの原因をたどりやすくしてくれる

エラーの委譲

自分のコードの文脈で利用可能なものよりも、 エラーの処理法を規定する情報やロジックがより多くある呼び出し元のコードに制御を明け渡す

ジェネリクス

  • ジェネリクスは、具体型や他のプロパティの抽象的な代役

  • 型引数の名前にはどんな識別子も使用できますが、Tを使用

  • "type"の省略形なので、Tが多くのRustプログラマの既定の選択

    fn largest<T>(list: &[T]) -> T {

  • 関数largestは、なんらかの型Tに関してジェネリック

  • の関数をi32値かchar値のどちらかで呼べる方法も表示

@cra_sabo
ITと旅行と本が好き。海外で働くことが目標。