Как в Rust выполнить общий набор действий с функциями, возвращающими разные типы - PullRequest
0 голосов
/ 26 мая 2020

Я немного новичок в Rust ie, поэтому, пожалуйста, go полегче!

Я пытаюсь написать простое приложение, которое генерирует поддельные табличные данные на основе простого списка типов столбцов.

Например, есть функции, которые создают поддельные имена и возраст:

fn name() -> String {
    FirstName(EN).fake()
}

fn age() -> i64 {
    rand::thread_rng().gen_range(0, 100)
}

Однако я борюсь с системой типов при попытке использовать эти функции для генерации данных на основе того, что в конечном итоге будет динамически предоставляемым списком типов:

pub fn generate()  {
    let generators = vec!["age", "name"];

    // generate each row
    for _ in 1..10 {
        // generate a value of the given type
        for gen_type in generators.iter() {
            // error[E0308]: match arms have incompatible types
            let generator = match gen_type.as_ref() {
                "age" => age,
                "name" => name,
                _ => println!("Error"),
            };

            let out = generator();

            // eventually I'll want to add some further logic here

            println!("{}", out);
        }
    }
}

Я понимаю проблему, переменная generator должна иметь тип stati c, но я не уверен, как я могу продолжить?

Следует ли инкапсулировать String и i64 в общую структуру c? Или можно как-нибудь Box? Еще раз извиняюсь за расплывчатый вопрос - указатель (без каламбура) в правильном направлении будет оценен!

1 Ответ

3 голосов
/ 26 мая 2020

Короче говоря, вам нужен полиморфизм.

В Rust у вас есть выбор между двумя разными механизмами:

  • Перечисления: закрытый набор возможностей.
  • Черты: открытый набор возможностей.

Черты более общие c (!), Но они немного сложнее; в общем, когда можно использовать оба, я бы рекомендовал перечисления.


Давайте применим это к вашей проблеме:

enum Property {
    Age(i64),
    Name(String),
}

fn name() -> Property {
    Property::Name(FirstName(EN).fake())
}

fn age() -> Property {
    Property::Age(rand::thread_rng().gen_range(0, 100))
}

Обратите внимание, что теперь обе функции имеют одинаковую сигнатуру типа!

Дополнительную информацию о перечислениях см. В Rust Book .

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