Rust に付け焼き刃で入門する 5
Rust に付け焼き刃で入門する 4 の続き。
6. Enum とパターンマッチング
6.1. Enumを定義する
Enumを定義する - The Rust Programming Language 日本語版
enum IpAddrKind { V4, V6, }
enum の定義。V4
と V6
を日本語ドキュメントでは列挙子と呼んでいるが、英語だと単純に variant。列挙子の名前は識別子として扱われているっぽいので、記号やスペースは含められないんだろうか? そもそも、Rust の識別子に使える文字種がどうなっているのか、まだ知らないが。
let four = IpAddrKind::V4; let six = IpAddrKind::V6;
列挙子のインスタンスを生成する。IpAddrKind::V4
や IpAddrKind::V6
は値。その両方を含んだ型が IpAddrKind
。
::
を使っているのは、関連関数の ::
と関係あるんだろうか?
enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from("::1"));
このようにして、列挙子に具体的なデータを格納することができる。列挙型はユニオン型のようになる。
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
Move
は匿名構造体をデータとして持つ列挙子。匿名構造体ってのは初めて出てきた気がする。他の箇所でも使えるんだろうか。
enum
と構造体にはもう1点似通っているところがあります:impl
を使って構造体にメソッドを定義できるのと全く同様に、enum
にもメソッドを定義することができるのです。
なるほど。関連関数は定義できるんだろうか?と思って試してみたらいけた。
#[derive(Debug)] enum Hoge { Foo(i32), Bar(bool), } impl Hoge { fn print(&self) { println!("{:?}", self); } // 関連関数を定義 fn make_bar(value: bool) -> Hoge { Hoge::Bar(value) } } fn main() { let foo = Hoge::Foo(123); let bar = Hoge::make_bar(true); // 関連関数を呼び出す foo.print(); // → Foo(123) bar.print(); // → Bar(true) }
Rustにはnullがありませんが、 値が存在するか不在かという概念をコード化するenumならあります。このenumが
Option<T>
で、 以下のように標準ライブラリに定義されています。
Haskell でいう Maybe
的なやつ。
Option<T>
は有益すぎて、初期化処理(prelude)にさえ含まれています。つまり、明示的にスコープに導入する必要がないのです。 さらに、列挙子もそうなっています:Some
とNone
をOption::
の接頭辞なしに直接使えるわけです。
しれっと使われている Some
や None
は、Option::Some
や Option::None
で enum だったのか。
では、
Option<T>
型の値がある時、その値を使えるようにするには、どのようにSome
列挙子からT
型の値を取り出せばいいのでしょうか?Option<T>
には様々な場面で有効に活用できる非常に多くのメソッドが用意されています; ドキュメントでそれらを確認できます。
Some(42)
から値 42
を取り出す方法は、この節では濁されている。ドキュメントを見てみると、unwrap()
メソッドでできるようだ。
6.2. matchフロー制御演算子
matchフロー制御演算子 - The Rust Programming Language 日本語版
パターンマッチ。説明されていないが、各アームが返す型はすべて同じでなければならないようだ。
Rustにおけるマッチは、包括的です: 全てのあらゆる可能性を網羅し尽くさなければ、コードは有効にならないのです。
これも Haskell など他の言語と同様。また、ワイルドカード的なプレースホルダとして、パターン中に _
が使える。
6.3. if letで簡潔なフロー制御
if letで簡潔なフロー制御 - The Rust Programming Language 日本語版
let some_u8_value = Some(0u8); match some_u8_value { Some(3) => println!("three"), _ => (), }
と
let some_u8_value = Some(0u8); if let Some(3) = some_u8_value { println!("three"); }
は等価。if let
と書かれていたので一瞬構造がよくわからなかったが、「普通の if 式の条件の部分に let Some(3) = some_u8_value
が入っている」と見ればよさそう。変数定義に使う let
と被っているのも紛らわしいが、パターンマッチのための「let <pattern> = <valiable>
」という特別な構文、という理解でいいんだろうか。
enum とパターンマッチ。若干独特な部分はあるが、変な概念はない。

プログラミング言語Rust 公式ガイド (アスキードワンゴ)
- 作者:Steve Klabnik,Carol Nichols,尾崎 亮太
- 発売日: 2019/07/05
- メディア: Kindle版