问题描述
我正在使用 filter
,但我不明白为什么我应该将 **x > 1
用于切片,而将 *x > 1
用于范围。
fn main() {
let a = [0,1,2,3];
let a_iter = a.iter().filter(|x: &&i32| **x > 1); // x: &&i32
let x: Vec<&i32> = a_iter.collect();
println!("{:?}",x);
let b = 0..4;
let b_iter = b.filter(|x: &i32| *x > 1); // x: &i32
let y: Vec<i32> = b_iter.collect();
println!("{:?}",y);
}
The docs 说它应该是 **x > 1
。
解决方法
slice::iter
,例如您的示例中的 a.iter()
,在对值的引用上生成迭代器。 Range
是产生非引用值的迭代器。
filter(<closure>)
方法采用 <closure>
,它通过引用获取迭代器值,因此如果您的迭代器已经生成引用,您将获得对引用的引用,如果您的迭代器生成非引用值然后您将获得对这些值的引用。
如果我们在两个示例中都使用 Vec
,区别会变得更容易理解:
fn main() {
let a = vec![0,1,2,3];
let a_iter = a.iter(); // iter() returns iterator over references
let x: Vec<&i32> = a_iter.filter(|x: &&i32| **x > 1).collect();
println!("{:?}",x);
let b = vec![0,3];
let b_iter = a.into_iter(); // into_iter() returns iterator over values
let y: Vec<i32> = b_iter.filter(|x: &i32| *x > 1).collect();
println!("{:?}",y);
}
,
这是因为在数组示例中,您首先调用 .iter()
来创建一个迭代器,它借用数组并因此借用其中的值; filter
的闭包参数接收迭代器 Item
的借用版本,因此再次借用它,使其成为 &&i32
。
在 Range
的情况下,您直接调用 filter
,因为 Range
is 是一个迭代器。因此,迭代器包含拥有的值,而 filter
中的闭包借用了它,这使得它的类型为 &i32
。
你可以看到,如果你在 let y = b;
行之后尝试 let b_iter = ...
:你会得到一个 use of moved value
错误,因为 b
被你的迭代器消耗了用于b.filter