In the link below I have a function that returns Result<HashMap<char,usize>,char>
. The body of that function calls a helper function that returns Result<usize,char>
. The errors are the same type signature, so returning on Err from the helper function causes no problem. In refactoring towards a more "functional" approach as an exercise I introduced a problem with the compiler. The first link shows the error, the second the workaround I employed. Is this the best way I can get around this problem?
The compiler error happens because you try to convert Result<T1, E>
into Result<T2, E>
where T1
and T2
are different types. While you know at runtime that the value is always a Err
at that location, the compiler doesn't know that. A quick fix is to extract E
from the Result
using err().unwrap()
and then wrap it into a Result
of a correct type (which will be inferred):
if err.len() > 0 { return Err(err[0].1.err().unwrap()); }
However, the function can be simplified if you use the fact that an iterator that yields Result
can be collected into a Result
with a collection (it will be Ok
if iterator yielded Ok
every time and Err
if the iterator returned an Err
):
pub fn nucleotide_counts(dna: &str) -> Result<HashMap<char, usize>, char> {
NUCLEOTIDES.iter().map(|&n| count(n,dna).map(|r| (n, r))).collect()
}
The .map(|r| (n, r))
uses a method of Result
that modifies the Ok
payload. We want to add n
to the Result
while keeping it the top level type so that collect()
works (i.e. it will work on Result<(char, usize), _>
but won't work on (char, Result<usize, _>)
.
Wow, what a great explanation! Makes it quite clear, thanks.