【问题标题】:Arrays and newtype pattern数组和新类型模式
【发布时间】:2022-12-12 23:56:45
【问题描述】:

我有一个类型,可以表示为 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.,因为在示例中我谈论的是以米为单位的人的身高。

【问题讨论】:

  • 由于 try_from 可能会在此处引发错误,因此将其作为 &amp;[f32] 传递并不总是安全的。为什么不使用from(),并在调用之前过滤所有无效值?
  • 我认为 try_from 更适合这种情况,因为我想通过设计保证这种类型不能存在于非常特定的 f32 子集中。因此,如果任何用户(将来包括我)尝试使用无效值创建它,它应该返回 Err。

标签: rust newtype


【解决方案1】:

也许调用Height::try_from(x).unwrap() 的宏?

类似于h!(3.0)

至于想要 &[f32] 的函数,要从 [Height] -> [f32] 安全地转换,你必须使用来自 Heights 的 f32 构造一个新的切片,这是 O(n) 所以不要太快。

一个更好的问题是为什么该函数是否需要 &[f32] 并且您可以更改它吗?

【讨论】:

  • 是的,宏也是我在想的。在我的特定用例中,我正在处理信号。我处理的信号是标准化的,所以它们的值在 0. 和 100. 之间,但是接受 &[f32] 的函数是一个过滤器,它通常可以接受任何 f32 值。所以我可以改变它,但最好保持原样。
猜你喜欢
  • 1970-01-01
  • 2013-02-09
  • 2012-07-14
  • 1970-01-01
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
相关资源
最近更新 更多