This code
let vec = vec![1, 3, 4, 5, 6];
for i in vec.iter().filter(|x| x % 2 == 0) {
println!("{}", i);
}
Produces the error
<anon>:4:36: 4:37 error: binary operation `%` cannot be applied to type `&&_` [E0369]
<anon>:4 for i in vec.iter().filter(|x| x % 2 == 0) {
^
I cannot understand the meaning of this error. Is this related to how the anonymous closure structure is created by the compiler?
The following code seems to be working.
for i in vec.iter().filter(|&x| x % 2 == 0) {
No, it is not related to how closure structure is created, it is a simple type error.
vec.iter(), when vec: Vec<T>, returns an iterator which yields references to its elements. filter() closure also accepts each element by reference (because otherwise elements would be consumed but this would defeat the whole purpose of filter()). Therefore, in vec.iter().filter(|x| ...) the closure argument x has type &&T, in your case, &&i32.
Rust numeric operators can't be applied to &&T, only to &T or T, so you need to dereference the closure argument somehow. There are two ways, first, as you noticed, you can use dereference pattern:
vec.iter().filter(|&x| x % 2 == 0)
// or even
vec.iter().filter(|&&x| x % 2 == 0)
Dereference pattern automatically dereferences the reference it is matching:
&x: &&i32 ==> x: &i32
&&x: &&i32 ==> x: i32
Alternatively, you can dereference the number directly:
vec.iter().filter(|x| *x % 2 == 0)
// or
vec.iter().filter(|x| **x % 2 == 0)
Related
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let even_numbers: Vec<i32> = numbers.iter().filter(|&n| n % 2 == 0).map(|n| *n).collect();
let even_numbers: Vec<_> = numbers.iter().filter(|&n| n % 2 == 0).map(|n| n).collect();
When the type is explicit I have to dereference n but if I don't state the type the compiler seems to know and automatically picks the value. Am I missing something, should it not be the other way around?
Why do I have to dereference with the explicit type but don't need to with _?
.iter() produces an iterator with an element type of &i32.
To collect into a Vec<i32>, you have to reference to copy the actual integer from the reference. That's what .map(|n| *n) does. (BTW .copied() exists for this purpose).
The Vec<_> tells the compiler "I just want a vector, but infer the element type" so it does just that and picks the element type from the iterator: &i32.
You can instead use .into_iter() on the original Vec, which will consume the vector and return an iterator of owned (not references) elements (i32) directly.
This question already has answers here:
How does Rust pattern matching determine if the bound variable will be a reference or a value?
(1 answer)
Why does pattern matching on &Option<T> yield something of type Some(&T)?
(1 answer)
Closed 2 years ago.
I'm struggling with destructuring/auto dereferencing.
I have a snippet of code, which works and I kind of see why - a is mutable and we pass a mutable reference to match. In the match statement we have a pattern which expects a mutable reference, and we take inner variables which are references to avoid moving them out.
let x = vec![1, 2];
let y = vec![3, 4];
let mut a = (x, y);
match &mut a {
&mut (ref aa, ref bb) => {}
}
I'm struggling to see why the following pattern works. I expect the pattern not to match to begin with, but it matches and aa and bb are both mutable references (no need for ref mut). I feel that this is some auto dereferencing at play:
match &mut a {
(aa, bb) => {
aa[0] = 2;
}
}
I feel that this is some auto dereferencing at play?
I wouldn't call it "auto" dereferencing because your intention to dereference the matched value is made explicit as part of your destructuring pattern. But yes, when you match a mutable reference against a pattern with a mutable reference it's the same as dereferencing the matched value. You can see this in action in this simpler code example:
fn main() {
for num in &[1, 2, 3] {
// type of `num` inside loop is &i32
// explicit deref required for equality check
if *num == 3 {
println!("found 3");
}
}
// implicit deref in destructuring pattern
for &num in &[1, 2, 3] {
// type of `num` inside loop is i32
// no need for explicit deref operation now
if num == 3 {
println!("found 3");
}
}
}
playground
I know there's probably a prime standard built-in function but my point here is learning rust lang.
The goal of this function is to get a collection of prime numbers given a range of numbers.
fn main() -> () {
let n = 1..20;
let primes: Vec<u32> = Vec::new();
for val in n {
primes.push( (1..20).filter(|x| x / val == 1 && x % val == 0).collect() );
println!("we got: {}", primes[val-1]);
}
// expecting primes to be [2, 3, 5, 7, 11, 13, 17]
}
compiler complains about
error[E0308]: mismatched types
--> src/main.rs:5:22
|
5 | primes.push( (1..20).filter(|x| x / val == 1 && x % val == 0) );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u32, found struct `std::iter::Filter`
|
= note: expected type `u32`
found type `std::iter::Filter<std::ops::Range<{integer}>, [closure#src/main.rs:5:37: 5:69 val:_]>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
what I'm doing wrong here? I'm having hard time with all that ownership, referencing and lifetime thingy
push can only push a single element onto a vector, e.g.
primes.push(2);
However, collect() doesn't yield a single element here; instead, it yields a collection that implements FromIterator.
To extend a Vec by the contents of an iterator, we use its Extend implementation instead:
primes.extend((1..20).filter(|x| x / val == 1 && x % val == 0));
Note that collect is missing now.
That being said, both extend and push need a mut Vec, so make sure to make primes mutable. Also keep in mind that your current code yields the wrong result, as it will add all numbers; that's not a Rust problem, however, but an algorithm one.
I have a vector of numbers and use the windows(2) method to create an iterator that gives me neighbouring pairs. For example, the vector [1, 2, 3] is transformed into [1, 2], [2, 3]. I want to use the find method to find a slice that fulfills a specific condition:
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; //For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
//...
None
}
I get an error:
error[E0005]: refutable pattern in function argument: `&&[]` not covered
--> src/lib.rs:6:43
|
6 | let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
| ^^^^^^^^ pattern `&&[]` not covered
I don't know what that error means: the list cannot have less than two elements, for example. Maybe the closure parameter is wrong? I tried to vary it but that didn't change anything. a and b are being properly detected as u64 in my IDE too. What is going on here?
You, the programmer, know that each iterated value will have a length of 2, but how do you know that? You can only tell that from the prose documentation of the function:
Returns an iterator over all contiguous windows of length size. The windows overlap. If the slice is shorter than size, the iterator returns no values.
Nowhere does the compiler know this information. The implementation of Windows only states that the iterated value will be a slice:
impl<'a, T> Iterator for Windows<'a, T> {
type Item = &'a [T];
}
I'd convert the slice into an array reference, discarding any slices that were the wrong length (which you know cannot happen):
use std::convert::TryFrom;
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; // For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list
.windows(2)
.flat_map(<&[u64; 2]>::try_from)
.find(|&&[a, b]| b - a == g)?;
//...
None
}
See also:
How to convert a slice into an array reference?
How can I find a subsequence in a &[u8] slice?
How do I imply the type of the value when there are no type parameters or ascriptions?
Alternatively, you could use an iterator of integers and chunk it up.
See also:
Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?
At some point in the future, const generics might be stabilized and allow baking the array length into the function call and the return type.
See also:
Is it possible to control the size of an array using the type parameter of a generic?
I was reading the chapter on higher order functions of Rust by Example. Where they present the following canonical example:
fn is_odd(n: u32) -> bool {
n % 2 == 1
}
fn main() {
let upper = 1000;
println!("imperative style: {}", acc);
let sum_of_squared_odd_numbers: u32 =
(0..).map(|n| n * n) // All natural numbers squared
.take_while(|&n_squared| n_squared < upper) // Below upper limit
.filter(|&n_squared| is_odd(n_squared)) // That are odd
.fold(0, |acc, n_squared| acc + n_squared); // Sum them
}
Simple enough. But I realized that I don't understand the type of parameter n_squared. Both take_while and filter accept a function that takes a parameter by reference. That makes sense to me, you want to borrow instead of consuming the values in the map.
However, if n_squared is a reference, why don't I have to dereference it before comparing its value to limit or equally surprising; why can I pass it directly to is_odd() without dereferencing?
I.e. why isn't it?
|&n_squared| *n_squared < upper
When I try that the compiler gives the following error:
error[E0614]: type `{integer}` cannot be dereferenced
--> src\higherorder.rs:13:34
|
13 | .take_while(|&n_squared| *n_squared <= upper)
|
Indicating that n_squared is an i32 and not &i32. Looks like some sort pattern matching/destructuring is happening here, but I was unable to find the relevant documentation.
You are using function parameter destructuring:
|&n_squared| n_squared < upper
is functionally equivalent to:
|n_squared| *n_squared < upper
To understand this better, imagine you're passing a tuple of type &(i32, i32) to a lambda:
|&(x, y) : &(i32, i32)| x + y