前回はクロージャ。今回はまたも寄り道、NoneとSomeは仲間だけれど、anyは違う件です。Rustのソースコードを読んでいてよく調べもせず、Noneは定数、Someとanyは何かの述語みたいなものと勝手に想像してたのはハズレました。Someは大文字始まりだし、anyは小文字なのでそれみりゃわかるだろ、という話ですが。
※「やっつけな日常」投稿順 Index はこちら
今回参照させていただいておりますドキュメント
いつもお世話になっております『Rust By Example 日本語版』様の以下のページを参照させていただいております。
まずNoneとSomeについては以下のページです。
ううむ、Optionというタイトルのページの下にNoneとSomeが隠れている(隠れているわけじゃない、多分)のは予想外でしたぞ。
anyについては以下のページです。
結論から言えば、NoneとSomeは、Option<T>型の列挙型のただ2つの値(列挙子みたいなもの)であり、anyは「イテレータ」です。なんだか、Someとanyは対になるように勝手に想像していたのは大外れ。
NoneとSome
Option<T> なる列挙型の値、ジェネリックなので、<T>のところに具体的な型が入るハズ。 一番簡単なところで32ビット整数型 i32 であれば、Option<i32> 型という感じですかね。そしてSome(なんじゃら)の中のなんじゃらにはi32型の値が詰まると。Someというのは<T>を入れる便利な入れ物だったのね。そしてNone。これはOption<i32> 型であれば、Some()に入れるような整数が存在しないときに使うらしいです。エラーとか、なんだとか、こんだとか?
Noneが戻ってくれば、当然 i32としての処理はできないので、別ルートでしまつ。Someであればi32が載っているハズ。ただしSomeに包装されているので開梱作業が必要と。
any
詳しくは上記のページなどご参照あれ。元のイテレータ(クロージャに捕捉される)に引っ付いて、その中に条件を満たす要素があれば trueを返し、なければ false を返すイテレータだそうな。そして元のイテレータを消費することはない、と。条件のところには前回やったクロージャを与えるのだ、と。分かったような、なんだかな~。でも実際に動かしてみればさほどでもないっす。
実験用のソース
以下では、
-
- 2つの配列 lis0 と lis1 に対して anyを使って 5 なる要素が入っているか否かを判定してみる
- 引数によっていOption<i32>型を返す some_if_plus()関数の返す値と、Someが返る場合は、その中身の開梱をしてみる
を試みてます。こんな感じ。
fn some_if_plus(arg: i32) -> Option<i32> { if arg > 0 { Some(arg) } else { None } } fn main() { let lis0 = [1, 2, 4]; let lis1 = [1, 2, 5]; println!("itr0: {}", lis0.iter().any(|&x| x == 5)); println!("itr1: {}", lis1.iter().any(|&x| x == 5)); println!("None(Debug): {:?}", some_if_plus(-1)); println!("Some(Debug): {:?}", some_if_plus(1)); println!("Some(unwarp): {}", some_if_plus(1).unwrap()); match some_if_plus(1) { None => println!("None"), Some(dat) => println!("{}", dat), } }
実行結果
実行結果が以下に。anyで判定できているみたいだし、Someの中身も取り出せているようです。
急に None とか Some とか言われても知らんよな~。