rust - 在没有特征(move_ref_pattern)或 mem::replace 的情况下处理具有组合移动和参考的模式的策略是什么?
问题描述
如果不使用该功能#![feature(move_ref_pattern)]
,那么在模式中同时处理移动和引用匹配的策略是什么?
通常,我有一个例程通过引用传递参数和通过移动传递参数。我想匹配它们之间的元组,因为它让我更容易看到不同的组合。同时,我想适当地使用第二个参数中的内存,因为它已经由例程拥有。
目前,我处理它的方式是匹配一个可变引用,然后调用std::mem::replace
以访问该值。这对我来说感觉很笨拙,我想看看是否有更好的方法来处理这个问题。
在这个大多数人为的示例中,该结构F64
用于防止被调用:Copy
// Cloneable, but not copyable float type
#[derive(Clone, Debug)]
enum MyFloat {
Zero,
Num(F64),
}
#[derive(Clone, Debug)]
struct F64(f64);
// Consume y, but not x
fn my_add(x: &MyFloat, mut y: MyFloat) -> MyFloat {
match (x, &mut y) {
(MyFloat::Zero, MyFloat::Zero) => MyFloat::Zero,
(MyFloat::Zero, y @ MyFloat::Num(_)) => std::mem::replace(y, MyFloat::Zero),
(MyFloat::Num(_), MyFloat::Zero) => x.clone(),
(MyFloat::Num(x), MyFloat::Num(y)) => {
let y = std::mem::replace(y, F64(0.));
MyFloat::Num(my_add_driver(x, y))
}
}
}
fn my_add_driver(x: &F64, y: F64) -> F64 {
F64((*x).0 + y.0)
}
// Run the program
fn main() {
let x = MyFloat::Num(F64(1.2));
let y = MyFloat::Num(F64(2.3));
println!("{:?} + {:?} = {:?}", x, y.clone(), my_add(&x, y));
}
在这里,y
作为可变引用传递给匹配,这解决了模式匹配的移动引用问题。但是,我们必须使用std::mem::replace
. 有没有更好的方法来处理这个?
解决方案
您可以像这样稍微简化它:
fn my_add(x: &MyFloat, y: MyFloat) -> MyFloat {
// match on y by value, not by ref:
match (x, y) {
(MyFloat::Zero, MyFloat::Zero) => MyFloat::Zero,
(MyFloat::Zero, y @ MyFloat::Num(_)) => y,
(MyFloat::Num(_), MyFloat::Zero) => x.clone(),
(MyFloat::Num(x), MyFloat::Num(ref mut y)) => {
let y = std::mem::replace(y, F64(0.));
MyFloat::Num(my_add_driver(x, y))
}
}
}
mem::replace()
只有使用该move_ref_pattern
功能或使用类似于以下的辅助方法才能摆脱其他调用Option::as_ref()
:
impl MyFloat {
fn as_ref_option(&self) -> Option<&F64> {
match self {
MyFloat::Zero => None,
MyFloat::Num(f) => Some(f),
}
}
}
// Consume y, but not x
fn my_add(x: &MyFloat, y: MyFloat) -> MyFloat {
match (x.as_ref_option(), y) {
(None, MyFloat::Zero) => MyFloat::Zero,
(None, y @ MyFloat::Num(_)) => y,
(Some(_), MyFloat::Zero) => x.clone(),
(Some(x), MyFloat::Num(y)) => MyFloat::Num(my_add_driver(x, y)),
}
}
推荐阅读
- c# - 来自 Swagger 和 CastleWindsor 的 Azure 运行时错误
- c++ - c ++输入for循环后跟另一个输入
- javascript - 从 Spotify Web Playback 流中读取输出音频数据
- config - 在 Debian 中编译 honeyd 时出错
- matlab - 如何从总体矩阵中获取可复制的随机样本?(Matlab)
- swift - 通过电话号码解析 快速解析
- kotlin - Kotlin:防止 == 编译错误类型
- python - Keras LSTM 多维输出错误 - 预期 time_distributed_17 具有 3 维,但得到的数组具有形状 (1824, 3)
- sql - 在 Postgres 中将嵌套键值添加到 JSONB
- python - 如何在列表的所有元素中的某个点之后删除字符串?