我试图编写一个涉及过滤和折叠数组的程序。我一直在使用The Rust Programming Language, first edition作为参考,但我不明白当我在数组上形成迭代器时会发生什么。这是一个例子:
fn compiles() {
let range = (1..6);
let range_iter = range.into_iter();
range_iter.filter(|&x| x == 2);
}
fn does_not_compile() {
let array = [1, 4, 3, 2, 2];
let array_iter = array.into_iter();
//13:34 error: the trait `core::cmp::PartialEq<_>` is not implemented for the type `&_` [E0277]
array_iter.filter(|&x| x == 2);
}
fn janky_workaround() {
let array = [1, 4, 3, 2, 2];
let array_iter = array.into_iter();
// Note the dereference in the lambda body
array_iter.filter(|&x| *x == 2);
}
在第一个函数中,我遵循范围内的迭代器不占用所有权,因此我必须在&x
的lambda中使用filter
,但我不会这样做。理解为什么数组的第二个例子表现不同。
答案 0 :(得分:30)
在这种情况下,强制编译器告诉您变量的类型非常有用。让我们通过将闭包参数分配给不兼容的类型来触发类型错误:
array_iter.filter(|x| { let () = x; true });
这失败了:
error[E0308]: mismatched types
--> src/main.rs:12:33
|
12 | array_iter.filter(|x| { let () = x; true });
| ^^ expected &&{integer}, found ()
|
= note: expected type `&&{integer}`
found type `()`
现在我们知道x
的类型是&&{integer}
- 对某些类整数的引用的引用。然后,我们可以与之匹配:
fn hooray() {
let array = [1, 4, 3, 2, 2];
let array_iter = array.into_iter();
array_iter.filter(|&&x| x == 2);
}
现在问题变成&#34;为什么它是对参考的引用&#34;?简短版本是iterator of an array returns references(参见type Item = &'a T
部分)。此外,Iterator::filter
passes a reference关闭以阻止移动并随后丢失非Copy
类型。
答案 1 :(得分:22)
数组是Rust中的类型[T; N]
,适用于任何元素类型T
和常量数N
。这是一个固定大小的阵列。
Rust目前没有为数组实现按值迭代器。所有数组都强制转换为切片(类型[T]
),并且切片方法因此而在数组上可用。数组也得到切片的迭代器,它被称为std::slice::Iter<'a, T>
并且具有&'a T
类型的元素:它通过引用迭代!
这就是为into_iter()
上的Range<i32>
生成i32
的迭代器而into_iter()
上的[i32; 5]
生成&i32
的迭代器的原因。
答案 2 :(得分:1)
正如Shepmaster和bluss所说,你可以查看提到的documentation for the array type:
大小从0到32(含)的数组实现以下内容 如果元素类型允许,则为traits:
IntoIterator
(已针对&[T; N]
和&mut [T; N]
实施)
正如它所说,这仅适用于参考,并反映在Item
类型中:type Item = &'a T
和type Item = &'a mut T
。