RustのIteratorを使って繰り返し処理を実行して理解しよう

2021-11-15

はじめに

イテレータとは、リストやベクターなどに対して順番に処理を施す抽象化を指します。 for文で書くような処理はイテレータでも実装が可能で、場合によっては処理を簡潔に書けます。

Iteratorトレイトを実装するには3つの手順があります。

  1. Iteratorが出力する型の選定
  2. Itemに紐付け
  3. next()関数の実装

実装例

構造体

struct Iter {
    current: i128,
    max: i128,
}

impl Iterator for Iter {
    type Item = i128;

    fn next(&mut self) -> Option<i128> {
        self.current += 1;
        if self.current - 1 < self.max {
            Some(self.current - 1)
        } else {
            None
        }
    }
}

fn main() {
    let ite = Iter {
        current: 0,
        max: 10,
    };

    for num in ite {
        println!("it:{}", num)
    }
}

フィボナッチ数列

この手の話でよく例題に上がるのが、フィボナッチ数列です。

$$ F_0 = 0 \n F_1 = 1$$
struct Iter {
    current: i128,
    nextval: i128,
}

impl Iterator for Iter {
    type Item = i128;

    fn next(&mut self) -> Option<i128> {
        let new_next = self.current + self.nextval;
        self.current = self.nextval;
        self.nextval = new_next;
        Some(self.current)
    }
}

fn main() {
    let ite = Iter {
        current: 0,
        nextval: 1,
    };

    for num in ite {
        println!("it:{}", num)
    }
}

実行結果

実行するとオーバーフローするまで出力され続けます。

Compiling hello-learn v0.1.0 (E:\SourceCode\Rust\hello-learn)
  Finished dev [unoptimized + debuginfo] target(s) in 0.60s
   Running `E:\SourceCode\Rust\hello-learn\target\debug\hello-learn.exe`
it:1
it:1
it:2
it:3
it:5
it:8
it:13
it:21
it:34
it:55
it:89
it:144
it:233
it:377
it:610
it:987
it:1597
it:2584
it:4181
it:6765
it:10946
it:17711
it:28657
it:46368
it:75025
it:121393
it:196418
it:317811
it:514229
it:832040
it:1346269
it:2178309
it:3524578
it:5702887
it:9227465
it:14930352
it:24157817
it:39088169
it:63245986
it:102334155
it:165580141
it:267914296
it:433494437
it:701408733
it:1134903170
it:1836311903
it:2971215073
it:4807526976
it:7778742049
it:12586269025
it:20365011074
it:32951280099
it:53316291173
it:86267571272
it:139583862445
it:225851433717
it:365435296162
it:591286729879
it:956722026041
it:1548008755920
it:2504730781961
it:4052739537881
it:6557470319842
it:10610209857723
it:17167680177565
it:27777890035288
it:44945570212853
it:72723460248141
it:117669030460994
it:190392490709135
it:308061521170129
it:498454011879264
it:806515533049393
it:1304969544928657
it:2111485077978050
it:3416454622906707
it:5527939700884757
it:8944394323791464
it:14472334024676221
it:23416728348467685
it:37889062373143906
it:61305790721611591
it:99194853094755497
it:160500643816367088
it:259695496911122585
it:420196140727489673
it:679891637638612258
it:1100087778366101931
it:1779979416004714189
it:2880067194370816120
it:4660046610375530309
it:7540113804746346429
it:12200160415121876738
it:19740274219868223167
it:31940434634990099905
it:51680708854858323072
it:83621143489848422977
it:135301852344706746049
it:218922995834555169026
it:354224848179261915075
it:573147844013817084101
it:927372692193078999176
it:1500520536206896083277
it:2427893228399975082453
it:3928413764606871165730
it:6356306993006846248183
it:10284720757613717413913
it:16641027750620563662096
it:26925748508234281076009
it:43566776258854844738105
it:70492524767089125814114
it:114059301025943970552219
it:184551825793033096366333
it:298611126818977066918552
it:483162952612010163284885
it:781774079430987230203437
it:1264937032042997393488322
it:2046711111473984623691759
it:3311648143516982017180081
it:5358359254990966640871840
it:8670007398507948658051921
it:14028366653498915298923761
it:22698374052006863956975682
it:36726740705505779255899443
it:59425114757512643212875125
it:96151855463018422468774568
it:155576970220531065681649693
it:251728825683549488150424261
it:407305795904080553832073954
it:659034621587630041982498215
it:1066340417491710595814572169
it:1725375039079340637797070384
it:2791715456571051233611642553
it:4517090495650391871408712937
it:7308805952221443105020355490
it:11825896447871834976429068427
it:19134702400093278081449423917
it:30960598847965113057878492344
it:50095301248058391139327916261
it:81055900096023504197206408605
it:131151201344081895336534324866
it:212207101440105399533740733471
it:343358302784187294870275058337
it:555565404224292694404015791808
it:898923707008479989274290850145
it:1454489111232772683678306641953
it:2353412818241252672952597492098
it:3807901929474025356630904134051
it:6161314747715278029583501626149
it:9969216677189303386214405760200
it:16130531424904581415797907386349
it:26099748102093884802012313146549
it:42230279526998466217810220532898
it:68330027629092351019822533679447
it:110560307156090817237632754212345
it:178890334785183168257455287891792
it:289450641941273985495088042104137
it:468340976726457153752543329995929
it:757791618667731139247631372100066
it:1226132595394188293000174702095995
it:1983924214061919432247806074196061
it:3210056809456107725247980776292056
it:5193981023518027157495786850488117
it:8404037832974134882743767626780173
it:13598018856492162040239554477268290
it:22002056689466296922983322104048463
it:35600075545958458963222876581316753
it:57602132235424755886206198685365216
it:93202207781383214849429075266681969
it:150804340016807970735635273952047185
it:244006547798191185585064349218729154
it:394810887814999156320699623170776339
it:638817435613190341905763972389505493
it:1033628323428189498226463595560281832
it:1672445759041379840132227567949787325
it:2706074082469569338358691163510069157
it:4378519841510949178490918731459856482
it:7084593923980518516849609894969925639
it:11463113765491467695340528626429782121
it:18547707689471986212190138521399707760
it:30010821454963453907530667147829489881
it:48558529144435440119720805669229197641
it:78569350599398894027251472817058687522
thread 'main' panicked at 'attempt to add with overflow', src\main.rs:10:24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `E:\SourceCode\Rust\hello-learn\target\debug\hello-learn.exe` (exit code: 101)

Overflowを引き起こしてますが、出てそうですね。

まとめ

Iteratorを理解するために、フィボナッチ数列を求めてみました。 まだもう少し触ってみたいと掴みきれないですが…まぁ良いんでないでしょうか。