Как отправить 'Some' с аргументом в функцию - PullRequest
0 голосов
/ 18 февраля 2020

Я пытаюсь отправить результат совпадения в функцию Foo, но результат совпадения имеет тип Some()

Как я могу отправить его в качестве аргумента Foo функция?

struct Person {
    name: Option<String>,
    lastname: Option<String>,
}

fn Foo(x: Option<String>) {
    println!("{:?}", x);
}

fn main() {
    let name = "Steve".to_string();
    let lastname = "Alvarez".to_string();
    let mut x: Option<Person> = Some(Person {
        name: Some(name),
        lastname: Some(lastname),
    });

    match x {
        Some(Person {
            name: ref a @ Some(_),
            lastname: ref b @ _,
        }) => Foo(a),
        _ => {}
    }
}

Ответы [ 2 ]

2 голосов
/ 18 февраля 2020

Шаг 1

Во-первых, ваш match x { Some(Person{...})... выглядит неправильно. Разверните его как Some(person) => foo(person.name).

struct Person {
    name: Option<String>,
    lastname: Option<String>,
}

fn foo(x: Option<String>) {
    println!("{:?}", x);
}

fn main() {
    let name = "Steve".to_string();
    let lastname = "Alvarez".to_string();
    let x: Option<Person> = Some(Person {
        name: Some(name),
        lastname: Some(lastname),
    });

    match x {
        Some(person) => foo(person.name),
        _ => {}
    }
}

Шаг 2: Сделайте его лучше

Принятие Option в качестве аргумента функции, я считаю, не очень похоже на Rust. (Я могу ошибаться, так как я также новичок в Rust.)

Кроме того, match, где опция None не выбрана, я тоже считаю антипаттерном. Вместо этого используйте комбинатор (map или and_then).

struct Person {
    name: Option<String>,
    lastname: Option<String>,
}

fn foo(x: String) {
    println!("{:}", x);
}

fn main() {
    let name = "Steve".to_string();
    let lastname = "Alvarez".to_string();
    let x: Option<Person> = Some(Person {
        name: Some(name),
        lastname: Some(lastname),
    });

    x.and_then(|person| person.name) // person.name is an Option -> thus use `and_then`
        .map(|n| foo(n));
}

Live Playground

0 голосов
/ 18 февраля 2020

Я думаю, что проблема с существующим кодом в том, что Foo потребляет Option, в то время как ваше совпадение получает ссылку на Option. Они должны соответствовать. Есть несколько подходов, которые будут работать здесь.

  1. Make Foo и совпадение оба используют значения. Это означает, что вы удаляете ref на спичках. Вы не сможете использовать значение Person после матча, так как оно будет разбито на составляющие части.
fn Foo(x: Option<String>) {
    println!("{:?}", x);
}

// ... 

    match x {
        Some(Person {
            name: a @ Some(_),
            lastname: b @ _,
        }) => Foo(a),
        _ => {}
    }

Make Foo и совпадение оба используют ссылки. Вы сохраняете ссылку на совпадение, но добавляете & к аргументу Foo.
fn Foo(x: &Option<String>) {
    println!("{:?}", x);
}

// ... 

    match x {
        Some(Person {
            name: ref a @ Some(_),
            lastname: ref b @ _,
        }) => Foo(a),
        _ => {}
    }

Клонируйте a, прежде чем передать его Foo. Foo и шаблон совпадения не меняется, но способ, которым вы звоните Foo, меняется незначительно
fn Foo(x: Option<String>) {
    println!("{:?}", x);
}

// ... 

    match x {
        Some(Person {
            name: ref a @ Some(_),
            lastname: ref b @ _,
        }) => Foo(a.clone()),
        _ => {}
    }

Конечно, в вашем конкретном случае вам вообще не нужно использовать сопоставление с шаблоном Вы можете просто использовать некоторые инструменты, которые уже существуют в Option, например map.

x.map(|p| Foo(p.name));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...