Есть ли способ разделить переменную внутри Option без использования операторов if? - PullRequest
0 голосов
/ 22 ноября 2018

Я хочу, чтобы приведенный ниже код работал, но поскольку map() становится владельцем Option, а для Option не существует функции clone(), следующее не компилируется.

fn main() {
    struct ItemA {
        a: String,
        b: String,
    }
    let foo = Some(ItemA {
        a: "A String".to_owned(),
        b: "B String".to_owned(),
    });
    // OR
    // let foo = None;

    let opA: Option<String> = foo.map(|c| c.a);
    let opB: Option<String> = foo.map(|c| c.b);
}
error[E0382]: use of moved value: `foo`
  --> src/main.rs:15:31
   |
14 |     let opA: Option<String> = foo.map(|c| c.a);
   |                               --- value moved here
15 |     let opB: Option<String> = foo.map(|c| c.b);
   |                               ^^^ value used here after move
   |
   = note: move occurs because `foo` has type `std::option::Option<main::ItemA>`, which does not implement the `Copy` trait

Было бы неплохо, если бы opA мог взять на себя владение ItemA.a (так что ему не нужно клонировать строки), а opB мог бы взять на себя владение ItemA.b

Можно ли обойтись без использования операторов if, чтобы проверить, является ли Option Some или None, развернуть и обернуть его по отдельности.

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

[T] здесь, похоже, не является clone() функцией для Option [...]

Это неправильно, есть , если внутренний тип также реализует clone.Так что в вашем случае просто добавьте #[derive(Clone)] к вашему struct ItemA.

Далее, вы можете использовать as_ref для создания Option<&T>, а затем использовать map.

let op_a = foo.as_ref().map(|c| &c.a);
let op_b = foo.as_ref().map(|c| &c.b);

println!("{:?}", op_a);
println!("{:?}", op_b);
0 голосов
/ 22 ноября 2018

Вы можете использовать map_or_else.

let (opA, opB) = foo.map_or_else(
    || (None, None),
    |c| (Some(c.a), Some(c.b))
);

Первая функция вызывается, если foo равно None, и возвращает два None с.Вторая функция вызывается, если foo равен Some и разделяет членов в кортеж.

Конечно, это не сильно спасет вас от простого match и, вероятно, будет сложнееследовать.

let (opA, opB) = match foo {
    None => (None, None),
    Some(c) => (Some(c.a), Some(c.b))
};

Кстати, Option действительно реализует Clone, но требует, чтобы содержащийся тип реализовывал Clone.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...