I'm trying to write a program that involves filtering and folding over arrays. I've been using The Rust Programming Language, first edition as a reference, but I don't understand what happens when I form iterators over arrays. Here is an example:
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);
}
(Rust playground)
In the first function, I follow that the iterator over the range does not take ownership, so I must take a &x
in filter
's lambda, but I don't understand why the second example with the array behaves differently.
One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.
The JavaScript Array. The filter() method takes in a callback function and calls that function for every item it iterates over inside the target array.
Iterating over an arrayYou can iterate over an array using for loop or forEach loop. Using the for loop − Instead on printing element by element, you can iterate the index using for loop starting from 0 to length of the array (ArrayName. length) and access elements at each index.
In cases like this, it's very useful to force the compiler to tell you the type of the variable. Let's trigger a type error by assigning the closure argument to an incompatible type:
array_iter.filter(|x| { let _: () = x; x == 2 });
This fails with:
error[E0308]: mismatched types
--> src/lib.rs:4:41
|
4 | array_iter.filter(|x| { let _: () = x; x == 2 });
| -- ^ expected `()`, found `&&{integer}`
| |
| expected due to this
Now we know the type of x
is a &&{integer}
- a reference to a reference to some kind of integer. We can then match against that instead:
fn hooray() {
let array = [1, 4, 3, 2, 2];
let array_iter = array.into_iter();
array_iter.filter(|&&x| x == 2);
}
The question now becomes "why is it a reference to a reference"? The short version is that the iterator of an array returns references (see the type Item = &'a T
part). In addition, Iterator::filter
passes a reference to the closure to prevent moving and subsequently losing non-Copy
types.
In Rust 1.51, you can use array::IntoIter
to get a by-value iterator:
fn hooray() {
let array = [1, 4, 3, 2, 2];
let array_iter = std::array::IntoIter::new(array);
array_iter.filter(|&x| x == 2);
}
Arrays are the type [T; N]
in Rust, for any element type T
and a constant number N
. It's a fixed size array.
Rust doesn't implement IntoIterator
for arrays at the moment. All arrays coerce to slices (type [T]
) and the slice methods are available on the array because of this. The arrays also get the slice's iterator, which is called std::slice::Iter<'a, T>
and has elements of type &'a T
: it iterates by reference!
This is why into_iter()
on a Range<i32>
produces an iterator of i32
and into_iter()
on a [i32; 5]
produces an iterator of &i32
.
If you need by value iterators for arrays and
You are using Rust 1.51 or newer, you can use array::IntoIter
:
fn does_now_compile() {
let array = [1, 4, 3, 2, 2];
let array_iter = std::array::IntoIter::new(array);
array_iter.filter(|&x| x == 2);
}
You are using older versions of Rust, by-value iterators have been implemented in the broader ecosystem, see arrayvec and literator.
As Shepmaster and bluss said, you can check the documentation for the array type, which mentions:
Arrays of sizes from 0 to 32 (inclusive) implement the following traits if the element type allows it:
IntoIterator
(implemented for&[T; N]
and&mut [T; N]
)
As it says, this is only for references, and is reflected in its Item
type: type Item = &'a T
and type Item = &'a mut T
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With