やっつけな日常(45) Rustに入ればRustに従え、イテレータで使えるメソッドその1

Joseph Halfmoon

今回からイテレータに入りました。前回、NoneとSome、そしてanyを「予習」しておいたおかげで多少は分かりやすかったんでないかい。でも今回は分かりやすい奴ら(メソッド)ばかり練習してみたから当たり前か。なんだかね、とってもいろいろいるのよね、よくわからない奴らが。<訂正あり

※2022年11月28日訂正: (1.10)をstd::iterのごとくに使用してますが、(1..10)はstd::ops::Range でした。共通するお名前で同様な機能のTraitsが実装されているのでイテレータではないのにイテレータとして練習してしまいました。以下コード中 (1..10)の代わりに[1, 2, 3, 4, 5, 6, 7, 8, 9].iter()とすれば「正式な」イテレータになるんでないの、と思われます。

※「やっつけな日常」投稿順 Index はこちら

VScodeで cargoで作ったrustのプロジェクトを開き、”(1..2).” と “.”(ピリオド)を打ったら冒頭のアイキャッチ画像のごとく、大量の補完候補が提示されました。みんなIterator一族のメソッドの方々。画像には a から c で始まるメソッドしか表示されていませんから、全体数はとんでもない数みたいです。

しかしま、Iterator一族を使えるようにしないとRustの「繰り返し」は分からないままなのでちゃんとやらないと。全貌は以下のドキュメントに書かれてます。

Trait std::iter::Iterator

ただね、上記のドキュメントでは以下のように experimental APIなどと書かれているものが結構あります。元来保守派なので、そいつらはとりあえずパス、先に簡単な奴らから(手抜き。)iterExperimentalAPI

今回練習してみたメソッド

今回使ってみたのは、戻り値が簡単な以下の奴らです。

    1. 真偽値を返すもの。all, any, eq, ge。
    2. 整数値を返すもの。count
    3. 前回登場の列挙型、Optionを返すもの。find、last、max, min, nth, potion

1は、geがあれば、leとかgtとかありがちな奴らは皆いるのですが、流石に疲れるので、eqとgeだけやりました。anyは前回も登場。どれもtrueかfalseを返すものどもです。allとanyは前々回やったクロージャを引数に与えて判定を迫る?もの。eqやgeは、イテレータ自体を比較?しているような構文です。

2は、Iteratorが返してくるItemの数を返すもの。ちょいと疑問があるのですが今回はそこには突っ込まず。

3は、前回登場の列挙型Optionを返すもの。前回やったNoneとSomeが返ってくる奴らです。findとpositionはクロージャを引数にとり、nthは整数をとりますが、last、max、minは無しでよろしいと。

実験に使ったソースコードは以下に。イテレータとしては1から10までのrangeをすべてに与えてみています。

fn main() {
    //all
    println!("all(<11): {}", (1..10).all(|x| x<11));
    println!("all(>5): {}", (1..10).all(|x| x>5));
    //any
    println!("any(x==5): {}", (1..10).any(|x| x == 5));
    println!("any(x=11): {}", (1..10).any(|x| x > 10));
    //eq
    println!("eq: {}", (1..10).eq(1..10));
    //ge
    println!("ge(1..9): {}", (1..10).ge(1..9));
    println!("ge(1..10): {}", (1..10).ge(1..10));
    println!("ge(1..11): {}", (1..10).ge(1..11));
    //count
    println!("count: {}", (1..10).count());
    //find
    match (1..10).find(|x| x == &4) {
        None => println!("None"),
        Some(dat) => println!("find(x==4): {}", dat),
    }
    //last
    match (1..10).last() {
        None => println!("None"),
        Some(dat) => println!("last: {}", dat),
    }
    //max
    match (1..10).max() {
        None => println!("None"),
        Some(dat) => println!("max: {}", dat),
    }
    //min
    match (1..10).min() {
        None => println!("None"),
        Some(dat) => println!("min: {}", dat),
    }
    //nth
    match (1..10).nth(5) {
        None => println!("None"),
        Some(dat) => println!("nth(5): {}", dat),
    }
    match (1..10).nth(10) {
        None => println!("nth(10): None"),
        Some(dat) => println!("nth(10): {}", dat),
    }
    //position
    match (1..10).position(|x| x == 7) {
        None => println!("None"),
        Some(dat) => println!("position(7): {}", dat),
    }
}
実機での実行結果

実機での実行結果が以下に。一応予定どおりでないかい。

Results

上みると5番目は6,7になるのは6番目ってことだね。0番目始まり。また、1..10であって、1..=10でないので lastは9、maxも9。countの数も9。

この辺の簡単な奴らの挙動は分かった。あたりまえか。

やっつけな日常(44) RustにいればRustに従え、NoneとSomeは仲間、anyは別 へ戻る

やっつけな日常(46) RustにいればRustに従え、イテレータで使えるメソッドその2 へ進む