rust 数组和新类型模式

z4iuyo4d  于 2022-12-13  发布在  其他
关注(0)|答案(2)|浏览(127)

我有一个类型,可以用f32表示,没有NaN、无穷大或负值,有一个最大值,一个普通的例子是人的身高(以米为单位),所以我用新的类型模式来表示它:

struct Height(f32);

impl TryFrom<f32> for Height {
    type Error = &'static str;

    fn try_from(value: f32) -> Result<Self, Self::Error> {
        if value.is_infinite() || value.is_sign_negative() || value > 3. {
            return Err("value was infinite");
        }
        Ok(Height(value))
    }
}

我不喜欢的是当我必须处理一个数组时,因为它应该声明为

let vec = vec![Height::try_from(3.).unwrap(), Height::try_from(2.).unwrap()];

添加了很多样板文件。而且当我需要将它传递给一个接受&[f32]的函数时,转换起来有点麻烦。
处理这种情况的惯用方法是什么?
编辑:如果将300.改为3.,因为在示例中,我指的是人的身高,单位是米。

5fjcxozz

5fjcxozz1#

也许一个宏要调用Height::try_from(x).unwrap()
比如h!(3.0)
对于需要&[f32]的函数,要安全地从[Height] -〉[f32]进行转换,你必须使用Height中的f32来构造一个新的切片,这是O(n)的,所以不要太快。
一个更好的问题是为什么函数想要&[f32],你能改变它吗?

yeotifhr

yeotifhr2#

最直接、最惯用的方法是使用迭代器和map

let raw_heights = vec![6.7, 5.8, 0.1, 4.4];

let heights: Vec<Height> = raw_heights.into_iter()
    .map(|rh| Height::try_from(rh).unwrap())
    .collect();

请参阅Rust Playground中的完整工作示例:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=61a42b0a86c64f4a75bf4094da88b301
您也可以使用macro_rules来实现这一点,但这是一种过度使用。

相关问题