Rust には失敗するかもしれない値を表す Result<T, E>
という型があります。
std::result::Result
そして iterate できることを表す Iterator
という trait があります。
std::iter::Iterator
また、Iterator
trait は要素型を表す関連型を持ちます。例えば
ここ間違っていました。String
は Iterator<Item=char>
を impl
しています。これは char
型を要素にもつ Iterator
であることを意味します。String
が直接 Iterator
を impl
しているのではありませんでした。
たまに Iterator<Item=Result<T, E>>
のようになっている型を見かけます(T, E にはなにかしら具体的な型が入っていると思ってください)。
例えば、std::io::stdin().bytes()
の返り値である std::io::Bytes は Iterator<Item=Result<u8>>
を impl
しています。
(ちょっとわかりにくいのですがここでの Result
は std::result::Result
ではなくて std::io::Result
です。std::io::Result
は std::result::Result<T, std::io::Error>
のエイリアスです。)
さて、このような Iterator
からすべての要素が Ok(_)
であれば Ok<Vec_>>
を、Err(_)
があれば Err<_>
を返すような処理を書きたいということは割りとよくあります。
で、これを一生懸命実装しようとしていたのですが、標準ライブラリの範囲内ですでに実装されていました。べんり。
let result = std::io::stdin().bytes().collect::<Result<Vec<\_>, \_>>();
これだけです。これで要件を満たす Result<Vec<_>, _>
が返って来ます。すばらしい。
タネは簡単な話で Result
が FromIterator
trait を impl
しているので collect
で変換が可能であるというお話でした。
std::iter::FromIterator