Reputation: 21
I have a function which returns a Result<u32, SomeError>
. I want to collect four values from this function, and collect them to sum them up. How can you propagate the error inside the map operator? I want to stop on the first error, and propagate the error up to the function which called it
Works
(0..4)
.map(|_| self.consume().unwrap())
.collect::<Vec<u32>>()
.iter()
.sum::<u32>();
Does not work
(0..4)
.map(|_| self.consume()?)
.collect::<Vec<u32>>()
.iter()
.sum::<u32>();
The compiler error is
.map(|_| self.consume()?)
----^^^^^^^^^^^^^^^----------------------
| |
| cannot use the `?` operator in a closure that returns `u32`
this function should return `Result` or `Option` to accept `?`
Upvotes: 2
Views: 1160
Reputation: 1503
Here you go:
(0..4)
.map(|_| self.consume())
.collect::<Result<Vec<u32>, _>>()?
.iter()
.sum::<u32>();
Upvotes: 2
Reputation: 71005
map()
is just an iterator adapater. It cannot propagate the error itself, since it doesn't run the code that can produce it. The executor of the code here is sum()
(actually, collect()
, but it is redundant here) and thus it should deal with the error (or a replacement).
In this case, you can exploit the fact that Result
implements Sum
, allowing you to sum into Result<T, E>
:
(0..4).map(|_| self.consume()).sum::<Result<u32, _>>()?;
collect()
also does the same, so you can collect into Result<Vec<T>, E>
for example.
Upvotes: 3
Reputation: 35512
There's actually a Sum
instance for Result<T, E>
that fits this usecase perfectly:
(0..4)
.map(|_| self.consume())
.sum::<Result<u32, _>>()?;
Upvotes: 2