Rust 当转换可能失败时,如何选择性地规范化值?
我希望定义一个函数,该函数检查两个值,并可选地将其中一个值更改为匹配类型。其动机是为数学公式执行自动转换。我的规则是:Rust 当转换可能失败时,如何选择性地规范化值?,rust,Rust,我希望定义一个函数,该函数检查两个值,并可选地将其中一个值更改为匹配类型。其动机是为数学公式执行自动转换。我的规则是: 两者都是i64,别管了 两者都是f64,别管了 一个是i64,一个是f64,将i64更改为f64 其他类型的其他规则 例如: fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {
- 两者都是i64,别管了
- 两者都是f64,别管了
- 一个是
,一个是i64
,将f64
更改为i64
f64
- 其他类型的其他规则
fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {
unimplemented!();
}
trait MapType {
type Output;
}
impl MapType for f64 {
type Output i64;
}
impl MapType for bool {
type Output u8;
}
您可以将具有关联类型的trait视为在类型之间映射的编译时函数。例如:
fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {
unimplemented!();
}
trait MapType {
type Output;
}
impl MapType for f64 {
type Output i64;
}
impl MapType for bool {
type Output u8;
}
对于可能需要的每个类型,可以实现MapType
,以提供到唯一输出的映射
您的案例是关于类型对的,您可以通过添加一个参数来扩展上述想法:
trait Normalize<T>: Sized {
type Norm;
}
为您想要的类型对实施它:
impl Normalize<u32> for f64 {
type Norm = f64;
}
impl Normalize<f64> for u32 {
type Norm = f64;
}
你很快就会意识到我在这里有点作弊,用了u32
而不是u64
。那是因为。如果你需要这些类型对,那么你仍然可以保持我所概述的方法,但是你需要定义你自己版本的TryInto
和TryFrom
traits,并为你需要的所有类型对自己实现它们。你能做一个包含所有可接受类型的枚举吗,然后在枚举上使用一个转换运算符进行规范化?为了简单起见,我没有显示额外的参数,运算符。每个运算符的转换不相同。将arg1视为左值,arg2视为右值,它们之间有一个二进制运算符。此规范化函数将附加到运算符枚举。转换失败。。。比如什么?这个问题是基于意见的,我投票决定就此结束。挑一个试试看。如果行得通,那太好了。如果没有,或者使用起来很烦人,选择另一个。如果你用尽了你的选项列表,问一个新问题寻找替代方案。因为这个问题的当前形式似乎离题了,你可能希望查看其他参考资料。欢迎在或上进行更多开放式问题和讨论。
impl<X> Normalize<X> for X {
type Norm = X;
}
fn normalize<A, B>(arg1: Option<A>, arg2: Option<B>) -> (Option<A::Norm>, Option<A::Norm>)
where
A: Normalize<B>,
A::Norm: TryFrom<B>,
{
(
arg1.and_then(|a| a.try_into().ok()),
arg2.and_then(|b| b.try_into().ok())
)
}
fn main() {
println!("{:?}", normalize(Some(1u32), Some(1u32))); // (Some(1), Some(1))
println!("{:?}", normalize(Some(1f64), Some(1u32))); // (Some(1.0), Some(1.0))
println!("{:?}", normalize(Some(1u32), Some(1f64))); // (Some(1.0), Some(1.0))
println!("{:?}", normalize(Some(1f64), Some(1f64))); // (Some(1.0), Some(1.0))
}