【发布时间】:2023-01-08 09:39:49
【问题描述】:
fn main() {
let v: Vec<i32> = vec![1, 2, 3];
// This works, of course.
println!("{}", foo(&v));
// Now let's create an "extra conversion" step:
let vs: Vec<&str> = vec!["1", "2", "3"];
// We want to "stream" straight from this vec. Let's create an
// iterator that converts:
let converting_iterator = vs.iter().map(|s| s.parse::<i32>().unwrap());
// This does not work
println!("{}", foo(converting_iterator));
}
fn foo<'a>(it: impl IntoIterator<Item=&'a i32>) -> i32 {
it.into_iter().sum()
}
我明白为什么第二行不起作用。它在 i32 而不是 &i32 上创建迭代器。我不能只是将 & 放入闭包中,因为那样会尝试引用一个临时值。
我很好奇的是,如果有任何以可以处理两种类型的可迭代对象的方式编写foo的方法?如果我只是将 .sum() 添加到创建 converting_iterator 的末尾,它就会正常工作。所以我觉得应该有一些“拦截”结果(即转换迭代器)的方法,通过那对某事,并有那东西打电话给.sum。
可能与 Borrow 或 AsRef 有关,但我无法从这些特征的文档中弄清楚。
【问题讨论】:
-
为什么不直接将
foo更改为接受impl Iterator<Item=i32>? -
因为第一行不再有效,
foo(&v)。 -
但也许我对什么是惯用语有误解。我假设一般来说,对于函数参数,如果你不这样做需要获得所有权,然后使用借用“更好”。
-
由于
i32是Copy类型,我可能会让调用者进行转换:foo(v.iter().copied())。您是否正在寻找也适用于非复制类型的解决方案?
标签: rust iterator traits ownership