kdnakt blog

hello there.

Rust dojo第23回を開催した

第23回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第23回の様子]

2021/12/22に第23回を開催した。

 

内容としてはRust By Example 日本語版の「8.5.3. バインディング」の続き、「8.6. if let」、「8.7. while let」まで取り組んだ。

 

参加者は、ちょっと増えて5人。今回は久しぶりに自分がドライバを担当した。

 

[学んだこと]

fn some_number() -> Option<u32> {
    Some(42)
}

fn main() {
    match some_number() {
        Some(n @ 42) => println!("The Answer: {}!", n),
        Some(n)      => println!("Not interesting... {}", n),
        _            => (),
    }
}

// The Answer: 42!が出力される
  • 前回やったように値のとりうる範囲を指定してバインドすることもできる
match some_number() {
    Some(n @ 40..=42) => {
        println!("The Answer: {}!", n)
    },
    _            => (),
}
  • 8.6. if let
  • ただ、matchを使ってデストラクトして処理を行うとインデントが2段になる上に、matchの網羅性を満たすための_ => ()が必要になりやや冗長
  • そんな時はif letを使うと良い
let number = Some(7);
if let Some(i) = number {
    println!("Matched {:?}!", i);
}

// Matched 7!と出力される
  • if letを使うと失敗時の処理もelseですむ
let letter: Option<i32> = None;

if let Some(i) = letter {
    println!("Matched {:?}!", i);
} else {
    println!("Didn't match a number. Let's go with a letter!");
}

// Didn't match a number〜と出力される
  • もちろんelse ifも使える
let emoticon: Option<i32> = None;

let i_like_letters = false;

if let Some(i) = emoticon {
    println!("Matched {:?}!", i);
} else if i_like_letters {
    println!("Didn't match a number. Let's go with a letter!");
} else {
    println!("I don't like letters. Let's go with an emoticon :)!");
}

// I don't like letters.〜と出力される
  • enumに対してもif letを用いることができる
// Our example enum
enum Foo {
    Bar,
    Baz,
    Qux(u32)
}

let a = Foo::Bar;

if let Foo::Bar = a {
    println!("a is foobar");
}

// a is foobarが出力される
  • else if letを使うこともできる
let b = Foo::Baz;

if let Foo::Bar = b {
    println!("b is foobar");
} else if let Foo::Baz = b {
    println!("b is foobaz");
}

// b is foobazが出力される
  • if letでもデストラクトした値を利用できる
let c = Foo::Qux(100);

if let Foo::Qux(value) = c {
    println!("c is {}", value); // c is 100と出力される
}

// @でバインドもできる
if let Foo::Qux(value @ 100) = c {
    println!("c is one hundred");
}
  • PartialEqトレイトを実装していないenum==で比較できないが、if letを用いることで条件式として利用できる
  • if letを使うと代入もできるが、unwrap_or()を使う方がシンプルに書ける
let number = Some(7);

let foo = if let Some(i) = number {
    i
} else {
    0
};
println!("{:?}", foo); // 7

// unwrap_or()を使うとより簡潔に書ける
let foo = number.unwrap_or(0);
println!("{:?}", foo); // 7
let mut optional = Some(0);

// optionalがNoneになったら終了
while let Some(i) = optional {
    if i > 9 {
        println!("Greater than 9, quit!");
        optional = None;
    } else {
        println!("`i` is `{:?}`. Try again.", i);
        optional = Some(i + 1);
    }
}

 

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。

デストラクトとバインドをいい感じに使いこなせるようになりたい。

 

今週のプルリクエストはこちら。

github.com