私的Rust学習メモ2(Enum Struct エラー制御など)


RustのEnum

Javaなどの言語におけるEnumというよりは、
Haskellにおける代数的データ型やTypescriptのDiscriminated Unionのような使い方をする
(それぞれの要素が別の型を持つことができる)

matchによる分岐

Enumによって処理を切り替える場合はmatchを使う

enum Hoge {
    Fuga(i32),
    Piyo(String),
}

fn hoge_func(hoge:Hoge) -> (){
    match hoge{
        Hoge::Fuga(i) => println!("FugaValue:{}",i),
        Hoge::Piyo(s) => println!("HogeValue:{}",s)
    }
}

なお、rustのmatchは文ではなく式なので値を返すこともできる。

標準のenum

javaのOpriontalに相当するOptionや例外処理に利用するResultもenumである。

Structs

  • Object指向言語におけるObjectのような構造化データを保存するもの
  • structはフィールドが全てCopy可能でも所有権が絡む。(自分でCopy可にしない限り)

Structの初期化

基本的に、全フィールドを指定する必要あり。
変数名とフィールド名が一致している場合は省略可能。
..でjavscriptのスプレッド構文のように展開することも可能。

struct Hoge {
    hoge:i32,
    count:u32
}

let h = Hoge{
      hoge:5,
      count:1
};

let count = 3;

let h2 = Hoge{
  count,
  ..h
}

structのフィールドの値として値を指定することは変数の代入と同様の動作なので、
所有権のかかわる変数の場合はstructのフィールド側に所有権が移行する。

Structの生成とスコープの問題

structのフィールドはデフォルトでprivate(同一モジュールのみからアクセス可能)である。
よって、一つでもpublicではない(pubがついていない)フィールドがあるstructはモジュール外から生成できなくなる。
このようなケースではStructを返すメソッド(selfなし)を定義しておく。
(Object指向言語におけるConstructorのようなもの)

メソッド

Structに紐づく関数を定義できる。
オブジェクト指向言語におけるメソッドのようなもの。
第一引数はselfで呼び出し元となるStructを取る。
selfの部分は、self,&self,&mut selfが使えるが、基本的に&self&mut selfのはず。
(メソッドに所有権を持っていかれると困るケースがほとんどのはず)。
メソッド定義でmutかどうかの使い分けができるため、
structがImmutableかどうかも変数宣言時にmutをつけるかどうかで制御できる。
(mut借用ができない場合、自分のフィールドを書き換えるメソッドは呼べない)


impl Hoge{
  fn hoge_method(&self){

  }
}

Associated Functions/関係関数

第一引数をselfにしないとAssociatedFunctionになる。
Object指向におけるstaticメソッドのような奴。

コンストラクタなどに利用できる。
標準だとString::from("hoge")とか。

Package クレート モジュール

Package

ビルドの単位。tomlファイルを持つ。
1つ以上のクレートを束ねる。

クレート

依存性管理で使われる単位。
複数のmoduleを木構造で持つ根本。

モジュール

クレートに木構造でぶら下がる。
スコープの単位。

段階ごとに分けて書く場合ディレクトリかファイル名を合わせる。

エラー制御

panic!

検知したからと言ってどうしようもない例外の時に投げる。
古いJavaの非検査例外のような感じ。

ResultEnum

Result型はOkかErrorを取る。
検査例外とかGoのエラー制御のような雰囲気。

Enumなのでmatchで分岐してもいいが、専用の記法やメソッドが用意されている。

unwrap/unwrap_or_else

ResultからOKという前提で値を取り出す。
実際Errorだった場合、unwrapはpanicを投げ、
or_elseの場合指定した処理を実行する。

Result型が戻り値の関数中での?

関数の戻り値がResult型の場合、内部では?で
jsのOptional chainingのようなことができる。

some_return_result()?.method_uses_ok_value()