let has_desc: bool = buffer.lines().map_while(Result::ok).any(|line| line.contains("## Description"));
Explanation:
map_while() basically "unwraps" the Results until it encounters the Err variant in which case it terminates the iterator, similar to your early return using ?.
any() searches the resulting iterator for any match of the predicate, i.e. whether any call of the closure returns true.
Ah, that is true. I think the best approach might be to hack together something with try_fold() (propagating any error and doing a Boolean or in the closure), if you want to avoid collecting into an intermediate Vec to handle the errors upfront. It might lose the early exit when true is returned though (but so does any() I think).
Edit: @nerditation has provided an example of the try_fold() approach below
try_fold() can achieve equivalent result, but is not as efficient as the original, due to no early break on success case. also, I feel a bit cheaty by using fold() and closure.
let has_desc = std::io::stdin().lines().try_fold(false, |found, line| {
// type annotation needed for the question mark operator
std::io::Result::Ok(found || line?.contains("## Description"))
})?;
I think I'm going to stick with the normal for loop for the sake of clarity, since it seems there's no way to be concise and clear using iterator chaining here. Thank you, everybody.