我认为这个问题最好通过一个例子来描述:
enum SensitiveVector<T> {
Empty,
Filled(Vec<T>),
}
impl<T> for SensitiveVector<T> {
pub fn append(mut self, other: Self) -> Self {
match (&self, &other) {
(Empty, Empty) => Empty,
(Empty, Filled(_)) => other,
(Filled(_), Empty) => self,
(mut vector @ Filled(_), Filled(other_items) => {
vector.0.append(other_items);
vector
}
}
}
}
我正在努力提高效率,而不是简单地克隆向量或类似的向量,而是有效地重新使用内存(希望如此)。 无论如何,匹配表达式的第四个臂是我的问题。我只是不知道如果该手臂匹配,如何将
other
实例的向量项附加到 self
。我尝试应用我在匹配臂中看到的任何语法,但它总是告诉我类型只是 &SensitiveVector<T>
,因此访问元组字段 0
是不可能的。
我知道代码可能很糟糕。但有人能告诉我该怎么做吗?当然,我可以只使用两个向量并创建一个新的
SensitiveVector
实例,但我认为扩展 self
更有效。
感谢您的帮助并解释我缺少的语法/概念/规则。
问题是双重的:
(&self, &other)
,因此模式中的值始终是共享引用,它们不能被拥有(返回)并且不能被修改。vector @ Filled(_)
会给你一个 vector: SensitiveVector
(最好的情况下,这里是一个 &SensitiveVector
),你无法从枚举本身访问枚举变体的字段,所以如果你的目标是,模式匹配很大程度上是浪费的更新内容。既然你无论如何都要按值获取
self
和 other
,第一个解决办法就是也匹配它们,这意味着你还需要返回在第二个和第三个臂中匹配的值,或者需要重建内容中的值:
enum SensitiveVector<T> {
Empty,
Filled(Vec<T>),
}
use SensitiveVector::*;
impl<T> SensitiveVector<T> {
pub fn append(mut self, other: Self) -> Self {
match (self, other) {
(Empty, Empty) => Empty,
(Empty, v @ Filled(_)) => v,
(v @ Filled(_), Empty) => v,
(mut vector @ Filled(_), Filled(other_items)) => {
vector.0.append(other_items);
vector
}
}
}
}
这并不能修复第四臂,但现在您应该将内部向量移出,合并向量,然后重新包装结果,而不是使用@模式:
enum SensitiveVector<T> {
Empty,
Filled(Vec<T>),
}
use SensitiveVector::*;
impl<T> SensitiveVector<T> {
pub fn append(mut self, other: Self) -> Self {
match (self, other) {
(Empty, Empty) => Empty,
(Empty, v @ Filled(_)) => v,
(v @ Filled(_), Empty) => v,
(Filled(mut v), Filled(other)) => {
v.extend(other);
Filled(v)
}
}
}
}
数值和参考之间存在一些不匹配。 由于您似乎想要处理值(使用参数来发出新值),因此我建议您一直使用值(特别是删除 match 语句中的引用)。
一旦 match 语句解构
self
或 other
,这两个值就不再存在,只是解构后的成员仍然存在,那么你必须从这些成员重新创建一个枚举(而不是尝试重用 self
或 other
作为一个整体)。
这是您的示例,进行了一些更正。
#[derive(Debug)]
enum SensitiveVector<T> {
Empty,
Filled(Vec<T>),
}
impl<T> SensitiveVector<T> {
fn append(
self,
other: Self,
) -> Self {
match (self, other) {
(Self::Empty, Self::Empty) => Self::Empty,
(Self::Empty, Self::Filled(other_items)) => {
Self::Filled(other_items)
}
(Self::Filled(items), Self::Empty) => Self::Filled(items),
(Self::Filled(mut items), Self::Filled(mut other_items)) => {
items.append(&mut other_items);
Self::Filled(items)
}
}
}
}
fn main() {
{
let sv1 = SensitiveVector::<i32>::Empty;
let sv2 = SensitiveVector::<i32>::Empty;
println!("empty and empty: {:?}", sv1.append(sv2));
}
{
let sv1 = SensitiveVector::<i32>::Empty;
let sv2 = SensitiveVector::Filled(vec![1, 2, 3]);
println!("empty and filled: {:?}", sv1.append(sv2));
}
{
let sv1 = SensitiveVector::Filled(vec![1, 2, 3]);
let sv2 = SensitiveVector::<i32>::Empty;
println!("filled and empty: {:?}", sv1.append(sv2));
}
{
let sv1 = SensitiveVector::Filled(vec![1, 2, 3]);
let sv2 = SensitiveVector::Filled(vec![4, 5, 6]);
println!("filled and filled: {:?}", sv1.append(sv2));
}
}
/*
empty and empty: Empty
empty and filled: Filled([1, 2, 3])
filled and empty: Filled([1, 2, 3])
filled and filled: Filled([1, 2, 3, 4, 5, 6])
*/