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);
}