首页 > 解决方案 > 使用 Rust,我如何对返回不同类型的函数执行一组通用操作

问题描述

我是一个 Rust 新手,所以请放轻松!

我正在尝试编写一个简单的应用程序,该应用程序根据一个简单的列类型列表生成假表格数据。

例如,具有创建假姓名和年龄的函数:

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变量需要有一个静态类型,但我不确定我该如何继续?

我应该封装在一个通用结构中吗Stringi64或者我可以Box以某种方式使用吗?再次为这个模糊的问题道歉 - 一个正确方向的指针(没有双关语)将不胜感激!

标签: rust

解决方案


简而言之,您需要多态性。

在 Rust 中,您可以在两种不同的机制之间进行选择:

  • 枚举:一组封闭的可能性。
  • 特征:一组开放的可能性。

特征更通用(!),但代价是更复杂一些;一般来说,当两者都可以使用时,我会推荐枚举。


让我们将此应用于您的问题:

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


推荐阅读