【问题标题】:How can I return an iterator over a slice?如何在切片上返回迭代器?
【发布时间】:2015-06-16 16:54:17
【问题描述】:
fn main() {
let vec: Vec<_> = (0..5).map(|n| n.to_string()).collect();
for item in get_iterator(&vec) {
println!("{}", item);
}
}
fn get_iterator(s: &[String]) -> Box<Iterator<Item=String>> {
Box::new(s.iter())
}
【问题讨论】:
标签:
iterator
closures
rust
【解决方案1】:
fn get_iterator<'a>(s: &'a [String]) -> Box<Iterator<Item=&'a String> + 'a> {
Box::new(s.iter())
}
这里的诀窍是我们从一个项目切片开始,该切片的生命周期为'a。 slice::iter 返回一个与切片具有相同生命周期的 slice::Iter。 Iterator 的实现同样返回具有该生命周期的引用。我们需要将所有生命联系在一起。
这解释了参数和Item=&'a 部分中的'a。那么+ 'a 是什么意思?有一个complete answer 和another with more detail。简短的版本是,一个具有内部引用的对象可以实现一个特征,所以我们在谈论一个特征时需要考虑这些生命周期。默认情况下,该生命周期为 'static,因为已确定这是通常的情况。
Box 不是严格要求的,但是当您不想处理可能作为实现基础的复杂类型(或者只是不想公开实现)时,您会看到这是正常的事情.在这种情况下,函数可以是
fn get_iterator<'a>(s: &'a [String]) -> std::slice::Iter<'a, String> {
s.iter()
}
但如果你添加.skip(1),类型将是:
std::iter::Skip<std::slice::Iter<'a, String>>
如果您涉及闭包,则目前无法指定类型,因为闭包是唯一的、匿名的、自动生成的类型!这些情况需要Box。