右上➚

プログラミングに関するメモをのこしていきます

Rust の Result と Iterator

Rust には失敗するかもしれない値を表す Result<T, E> という型があります。 std::result::Result

そして iterate できることを表す Iterator という trait があります。 std::iter::Iterator

また、Iterator trait は要素型を表す関連型を持ちます。例えば StringIterator<Item=char>impl しています。これは char 型を要素にもつ Iterator であることを意味します。 ここ間違っていました。String が直接 Iteratorimpl しているのではありませんでした。

たまに Iterator<Item=Result<T, E>> のようになっている型を見かけます(T, E にはなにかしら具体的な型が入っていると思ってください)。 例えば、std::io::stdin().bytes() の返り値である std::io::BytesIterator<Item=Result<u8>>impl しています。 (ちょっとわかりにくいのですがここでの Resultstd::result::Result ではなくて std::io::Result です。std::io::Resultstd::result::Result<T, std::io::Error>エイリアスです。)

さて、このような Iterator からすべての要素が Ok(_) であれば Ok<Vec_>> を、Err(_) があれば Err<_> を返すような処理を書きたいということは割りとよくあります。 で、これを一生懸命実装しようとしていたのですが、標準ライブラリの範囲内ですでに実装されていました。べんり。

let result = std::io::stdin().bytes().collect::<Result<Vec<_>, _>>();

これだけです。これで要件を満たす Result<Vec<_>, _> が返って来ます。すばらしい。

タネは簡単な話で ResultFromIterator trait を impl しているので collect で変換が可能であるというお話でした。 std::iter::FromIterator