はじめに
キューやスタックを扱うコードでは、次のような条件判定を書くことがよくあります。
- キュー/スタックが空ではなく、かつトップの要素がある条件を満たすか?
- キュー/スタックが空である、またはトップの要素がある条件を満たすか?
このような処理を簡潔に書くには、Rust 1.89で安定化したOption::is_some_and と Option::is_none_or が便利です。
is_some_and
is_some_andは、「OptionがSomeであり、かつその中身が指定した条件を満たすか?」をチェックします。
サンプルコード
let stack = vec![3, 5, 8];
if stack.last().is_some_and(|&x| x > 5) {
println!("トップの要素は 5 より大きい");
}
このコードでは、stack.last()がSomeであり、かつその値が5より大きい場合にtrueになります。
is_some_andを使わない場合
従来のRustでは、次のように書く必要がありました。
let stack = vec![3, 5, 8];
if !stack.is_empty() && *stack.last().unwrap() > 5 {
println!("トップの要素は 5 より大きい");
}
unwrapを使うため安全性が下がり、やや冗長な記述になります。
Rust 1.88以降のlet chainsを使う場合
Rust 1.88から導入されたlet chains構文を使うと、次のようにも書けます。
let stack = vec![3, 5, 8];
if let Some(&x) = stack.last() && x > 5 {
println!("トップの要素は 5 より大きい");
}
これも簡潔ですが、is_some_andの方が「ブール値を返す判定式」であることが明確です。
is_none_or
is_none_orは、「OptionがNoneである、または中身が条件を満たす」場合にtrueを返します。
「空ならOK、中身がある場合は条件を満たしている必要がある」といったケースに適しています。
サンプルコード
let queue = vec![10, 20, 30];
if queue.first().is_none_or(|&x| x < 50) {
println!("キューの先頭が50未満、または空です");
}
is_none_orを使わない場合
従来は次のように書く必要がありました。
let queue = vec![10, 20, 30];
if queue.is_empty() || *queue.first().unwrap() < 50 {
println!("キューの先頭が50未満、または空です");
}
この書き方ではunwrapを呼ぶ必要があり、安全性や意図の明確さがやや劣ります。
実行環境
- Rust:
rustc 1.89.0 (29483883e 2025-08-04)