Rust 如果蓄能器既不是复制型也不是可变的,是否可以使用折叠式防锈
我正试图做一个折叠式的工作,遇到了终身的问题。以下是我的代码的简化版本:Rust 如果蓄能器既不是复制型也不是可变的,是否可以使用折叠式防锈,rust,fold,Rust,Fold,我正试图做一个折叠式的工作,遇到了终身的问题。以下是我的代码的简化版本: struct A { v: i32, } let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }]; let max = v.iter().fold(None, |res: Option<A>, &item| { match res { Some(a) => if a.v >= item.v { Some(a) } else { Some(
struct A {
v: i32,
}
let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }];
let max = v.iter().fold(None, |res: Option<A>, &item| { match res {
Some(a) => if a.v >= item.v { Some(a) } else { Some(item) },
None => Some(item)
}});
如果我通过添加#[派生(复制,克隆)]
来创建一个复制类型,则第一个版本可以工作,但这并不总是一个选项
我试图在rust中搜索折叠示例,但我要么找到了累加器是副本类型(使用fold实现的i32求和)的示例,要么找到了累加器是容器且fold正在处理内容(扩展向量或类似内容)的示例
我还发现,但这与累加器的当前值不匹配
我可以使用for循环,但更喜欢fold语法。从
Vec::iter()
获得的迭代器生成对向量中元素的不可变借用引用(&a
);之后向量将保持不变
作为提醒,默认情况下,在生锈时使用一个值,使原始文件无法使用;只有在您拥有该项目的情况下才能执行此操作,即,您不能从借用的参考中移出。例外情况是类型为Copy
,这意味着它们“足够简单”,原始内存拷贝是正常的,不会使原始对象无效
因此,对于不是Copy
的任何类型,都不能直接从不可变引用赋值
有几种选择
首先,如果您可以实现或派生克隆
(这意味着您提供了一种可以复制对象的方法,可能不仅仅是一个原始副本),而不需要复制
,那么您可以显式克隆:
let max = v.iter().fold(None, |res: Option<A>, item| match res {
Some(a) => if a.v >= item.v { Some(a) } else { Some(item.clone()) },
None => Some(item.clone()),
});
移动在那里可以正常工作,但是Vec
不再存在
无论是哪种方式,您都需要复制(通过
复制
,克隆
,或其他更手动的方式)或移动-这取决于您的应用程序哪个更合适。编译器中有几个关于生命周期参数对闭包参数的推断的错误;您在这里遇到的一个已报告为。在res:Option
中,为&A
推断的生存期是错误的,这似乎是由于返回类型(即Option
)也具有生存期参数造成的。解决方法是让编译器推断出整个类型,这可以很好地工作,而不是在初始累加器值上给出类型提示(None
):
奖励:对于查找最大值的特定问题,您也可以使用。不需要注释
fn main() {
let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }];
let max = v.iter().max_by_key(|item| item.v);
println!("{:?}", max);
}
您能进一步解释一下原始代码给出错误的原因吗?总有一种解决方案是使用clone/copy或使用into_iter()来解决的,但它可以只使用引用来解决吗?我想在项目上获得另一个不可变的借用。我从
选项开始
,但不了解生命周期问题。整件事的开始是编译器不能干扰Some(a)
中a
的类型,我刚刚意识到如果我首先有None
匹配行,那么整件事在没有类型注释的情况下就可以工作,比如None=>Some(项)
将帮助编译器推断匹配到选项的返回类型,并具有正确的生存期。是否有该错误的链接?使用我能找到的最接近的匹配项编辑问题。有太多关于闭包的错误报告,有些错误相互矛盾!e、 在中,您需要指定参数的类型以避免编译器错误,这与这里的问题相反!谢谢,我在原始代码中折叠后有一个映射,这就是为什么我不能在max上指定类型,而在None上却没有指定。现在它工作得很好,max\u by_key
实际上是我所需要的,我太关注折叠了。正如我对另一个答案的评论一样,我刚刚意识到,如果我有None=>Some(item)
匹配,那么它可以帮助编译器正确推断累加器的类型,我不需要类型提示。
let max = v.into_iter().fold(None, |res: Option<A>, item| match res {
Some(a) => if a.v >= item.v { Some(a) } else { Some(item) },
None => Some(item),
});
#[derive(Debug)]
struct A {
v: i32,
}
fn main() {
let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }];
let max = v.iter().fold(None::<&A>, |res, item| { match res {
Some(a) => if a.v >= item.v { Some(a) } else { Some(item) },
None => Some(item)
}});
println!("{:?}", max);
}
fn main() {
let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }];
let max: Option<&A> = v.iter().fold(None, |res, item| { match res {
Some(a) => if a.v >= item.v { Some(a) } else { Some(item) },
None => Some(item)
}});
println!("{:?}", max);
}
fn main() {
let v = vec![A { v: 1 }, A { v: 2 }, A { v: 3 }];
let max = v.iter().max_by_key(|item| item.v);
println!("{:?}", max);
}