Почему map и map_err фиксируют одну и ту же переменную? - PullRequest
0 голосов
/ 20 сентября 2018

Я строю связанное будущее

ActorFuture<Item = Vec<String>, Error = Vec<String>, Actor = Self>

В случае успеха у него будет вектор строковых выходов всех фьючерсов, связанных с .and_then.При первой ошибке обработка прекратится, и я хочу вернуть успешные выходы фьючерса и окончательную (неудачную) будущую ошибку.Я хочу использовать один и тот же вектор для обработки обоих путей: хорошо и ошибаться.Но компилятор жалуется:

242 |                             .map(|o| {v.push(o); v})
    |                                  --- value moved (into closure) here
243 |                             .map_err(|e| {v.push(format!("{}", e)); v})
    |                                           ^ value captured here after move

Почему это так?Можно ли одновременно перейти на map и map_err?Это никогда не должно происходить в моем понимании.

Пример:

#[test]
fn test_map_and_map_err() {
    let mut v = Vec::new();
    Ok("foo".to_string())
        .map(|i| { v.push(i); v })
        .map_err(|e: String| { v.push(e); v });
}
error[E0382]: capture of moved value: `v`
 --> src/lib.rs:6:32
  |
5 |         .map(|i| { v.push(i); v })
  |              --- value moved (into closure) here
6 |         .map_err(|e: String| { v.push(e); v });
  |                                ^ value captured here after move
  |
  = note: move occurs because `v` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait

1 Ответ

0 голосов
/ 20 сентября 2018

Компилятор не знает, что замыкания, переданные в map и map_err, являются взаимоисключающими.Даже если это так, у него нет способа создать два замыкания, которые оба имеют одно и то же значение.

Вам необходимо использовать конструкцию, которая «прозрачна» для компилятора, например match:

#[test]
fn test_map_and_map_err() {
    let mut v = Vec::new();
    let r = Ok("foo".to_string())
        .map(|i| v.push(i))
        .map_err(|e: String| v.push(e));
    match r {
        Ok(()) => Ok(v),
        Err(()) => Err(v),
    };
}

Или вместо этого вы можете поменять значение:

#[test]
fn test_map_and_map_err() {
    use std::mem;
    let mut v = Vec::new();
    Ok("foo".to_string())
        .map(|i| {
            v.push(i);
            mem::replace(&mut v, vec![])
        }).map_err(|e: String| {
            v.push(e);
            mem::replace(&mut v, vec![])
        });
}
...