A division either returns a quotient or, if the divisor is zero, an error:
fn divide(a: f64, b: f64) -> Result<Success, Failure> {
match b {
0.0 => Err(Failure::Why(format!("divide by zero: {a}/{b}"))),
_ => Ok(Success { result: a / b }),
}
}
#[derive(Debug)]
struct Success {
result: f64,
}
#[derive(Debug)]
enum Failure {
Why(String),
}
In my main
function, I’d like to perform multiple divisions, and deal with the outcomes later:
fn main() {
let divisions = [(9.0, 3.0), (7.0, 0.0), (12.0, 4.0)];
let (worked, failed): (Vec<Result<Success, Failure>>, Vec<Result<Success, Failure>>) =
divisions
.iter()
.map(|d| divide(d.0, d.1))
.partition(|e| e.is_ok());
let errors: String = failed
.iter()
.map(|f| f.unwrap_err())
.map(|f| format!("{:?}", f))
.collect::<Vec<_>>()
.join(", ");
println!("errors: {}", errors);
}
However, this code doesn’t compile:
error[E0507]: cannot move out of `*f` which is behind a shared reference
--> src/main.rs:29:18
|
29 | .map(|f| f.unwrap_err())
| ^ ------------ `*f` moved due to this method call
| |
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*f` has type `Result<Success, Failure>`, which does not implement the `Copy` trait
The code compiles and works when using .as_ref()
, but I don’t understand why. My guess was that failed.iter()
turns my Vec
of Result
values into an Iter
of Result
references. I checked this theory using the following line:
let iter: std::slice::Iter<&Result<Success, Failure>> = failed.iter();
However, the compiler refutes my theory:
error[E0308]: mismatched types
--> src/main.rs:34:61
|
34 | let iter: std::slice::Iter<&Result<Success, Failure>> = failed.iter();
| ------------------------------------------- ^^^^^^^^^^^^^ expected `Iter<'_, &Result<Success, Failure>>`, found `Iter<'_, Result<Success, Failure>>`
| |
| expected due to this
|
= note: expected struct `std::slice::Iter<'_, &Result<_, _>>`
found struct `std::slice::Iter<'_, Result<_, _>>`
Where is Result<T, E>
turned into a &Result<T, E>
?