I am working through the rustlings exercises to learn Rust. I have reached the iterator3.rs exercise and am stuck. This exercise asks me to provide a line of code that will map results from one type to another as part of the operation; I need to fill in the line x= with the correct operation. There are two parts - the first reads in part:
let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
let x = ???
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
The next is the same with a slightly different format for the assertion of the output:
assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
I believe I understand that the first instance needs to return a Result that contains either a Vector of i32 or some error type. The second needs to return a Vector of Results that each have a i32 or an error type.
I am, however, generally having difficulty understanding how to determine what type is returned by the combinations of into_iter, map, and collect. I could use some help in learning how to reason about it or in getting compiler assistance.
Here is where I am so far:
I don't understand what the resultant type of division_results is. I have tried to use compiler error messages as well as the answer of this question to find out, but the results are opaque to me, perhaps because of lazy evaluation. For example, just replacing x with division_results so that assert will show the types, like this:
assert_eq!(format!("{:?}", division_results), "Ok([1, 11, 1426, 3])");
Gives me this result:
left: `"Map { iter: IntoIter([27, 297, 38502, 81]) }"`,
right: `"Ok([1, 11, 1426, 3])"`', exercises/standard_library_types/iterator3.rs:75:9
And it isn't clear what the left side results are as the iteration and map have not happened. The other various things I have tried provide similar results.
Thinking that the problem is lazy evaluation, I have also tried using collect to see if that will force evaluation. For example, calling collect at the end of the division_results line like this:
division_results = numbers.into_iter().map(|n| divide(n, 27)).collect();
Provides an error:
cannot infer type consider giving `division_results` a type
When I modify collect to say:
let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<i32>();
I get an error that I thought gave me a hint at the right type:
let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<i32>();
| ^^^^^^^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=std::result::Result<i32, DivisionError>>`
So I tried with the type shown in the error message:
let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<Result<i32, DivisionError>>();
Only to get this error:
let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<Result<i32, DivisionError>>();
| ^^^^^^^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
Clearly I am missing something. Perhaps you can tell me what?