我正在尝试让一个折叠功能起作用,但遇到了生命周期问题。这是我代码的简化版本:
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)
}});
这会导致出现错误
error[E0507]: cannot move out of borrowed content
。如果我按照之前的错误建议将闭包更改为
|res: Option<A>, ref item| …
,则在 Some(item)
处会出现类型不匹配的错误,解决该引用后回到了原始错误。我尝试在选项中使用引用,但是我遇到了生命周期问题:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> <anon>:6:67
|
6 | let maxV = v.iter().fold(None, |res: Option<&A>, &item| { match res {
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 6:58...
--> <anon>:6:59
|
6 | let maxV = v.iter().fold(None, |res: Option<&A>, &item| { match res {
| ___________________________________________________________^ starting here...
7 | | Some(a) => if a.v >= item.v { Some(a) } else { Some(&item) },
8 | | None => Some(&item)
9 | | }});
| |____^ ...ending here
note: ...so that types are compatible (expected std::option::Option<&main::A>, found std::option::Option<&main::A>)
--> <anon>:6:67
|
6 | let maxV = v.iter().fold(None, |res: Option<&A>, &item| { match res {
| ^^^
note: but, the lifetime must be valid for the method call at 6:13...
--> <anon>:6:14
|
6 | let maxV = v.iter().fold(None, |res: Option<&A>, &item| { match res {
| ______________^ starting here...
7 | | Some(a) => if a.v >= item.v { Some(a) } else { Some(&item) },
8 | | None => Some(&item)
9 | | }});
| |_____^ ...ending here
note: ...so that argument is valid for the call
--> <anon>:6:28
|
6 | let maxV = v.iter().fold(None, |res: Option<&A>, &item| { match res {
| ^^^^
第一个版本可以通过添加
#[derive (Copy, Clone)]
使A成为复制类型来实现,但这并不总是可行的。我尝试搜索rust中的折叠示例,但我要么找到了累加器是复制类型的示例(使用fold实现的i32求和),要么找到了累加器是容器且fold正在操作内容的示例(扩展向量或类似操作)。
我还发现了一个将值折叠到Option中的示例,但它不能匹配当前累加器的值。
我可以用for循环做到这一点,但更喜欢fold语法。
Option <&A>
,但是没有理解生命周期问题。整个问题的起因是编译器无法干涉Some(a)
中a
的类型,我才意识到如果我将None
匹配行放在第一位,则整个内容可以在没有类型注释的情况下工作,因为None => Some(item)
将帮助编译器推断出与正确生命周期相关的匹配返回类型为Option <&A>
。 - gumininja