"cannot deduce type for` _` "when using map on iter in Rust

I had a problem when I try to initialize a 2D array of booleans with random true / false values, but the compiler seems to be unable to infer the types that I need; I'm just wondering what I need to specify for the output mechanism in order to be able to solve this problem.

extern crate rand; fn main() { let mut grid = [[false; 10]; 10]; grid.iter_mut().map(|row| { [false; 10].iter().map(|_| { rand::random() }).collect() }); } 

Playground link (without rand::random() )

The error I get is

  | grid.iter_mut().map(|row| { [false; 10].iter().map(|_| { rand::random() }).collect() }); | ^^^ cannot infer type for `_` 
+5
source share
1 answer

Since the type [T; 10] [T; 10] implements Rand , where T: Rand , you can directly use rand::random() :

 extern crate rand; fn main() { let grid: [[bool; 10]; 10] = rand::random(); println!("{:#?}", grid); } 

As for the reasons why in your example the type inference is not obtained - here is a little simpler, which illustrates the problem:

 fn main() { let mut arr = [false; 10]; let mapped = arr.iter_mut().map(|_| rand::random()).collect(); println!("{:?}", arr); println!("{:?}", mapped); } 

Gives an error:

 error[E0282]: unable to infer enough type information about `_` --> src/main.rs:5:13 | 5 | let mapped = arr.iter_mut().map(|_| rand::random()).collect(); | ^^^^^^ cannot infer type for `_` | = note: type annotations or generic parameter binding required 

So we can specify the type:

 fn main() { let mut arr = [false; 10]; let mapped = arr.iter_mut().map(|_| rand::random()).collect::<[bool; 10]>(); println!("{:?}", arr); println!("{:?}", mapped); } 

Note the use of the "turbofish" ::<> operator after collection to indicate the type to collect, in this case ::<[bool; 10]> ::<[bool; 10]> . Unfortunately, here the compiler will complain:

 error[E0277]: the trait bound `[_; 10]: std::iter::FromIterator<bool>` is not satisfied 

So what is std::iter::FromIterator<bool> ? Well, consider the definition of the collect function:

 fn collect<B>(self) -> B where B: FromIterator<Self::Item> 

This means that any type you compile needs to implement FromIterator<Self::Item> . Arrays, unfortunately, do not implement FromIterator - but there are many possible types, for example, Vec , VecDeque , HashSet , BTreeSet , etc. Therefore, we can change the example:

 fn main() { let mut arr = [false; 10]; let mapped = arr.iter_mut().map(|_| rand::random()).collect::<Vec<bool>>(); println!("{:?}", arr); println!("{:?}", mapped); } 

However, this may not give you the result you were hoping for:

 [false, false, false, false, false, false, false, false, false, false] [true, false, false, true, true, false, true, false, true, true] 

So what gives? Why wasn't arr mutated, although it was declared mutable, and we used iter_mut ? The reason is that map creates a new object from an existing one - it does not display "in place". If you really want to display in place, you can use the following:

 fn main() { let mut arr = [false; 10]; let mapped = arr.iter_mut().map(|b| *b = rand::random()).collect::<Vec<()>>(); println!("{:?}", arr); println!("{:?}", mapped); } 

Yielding

 [true, false, true, true, true, false, false, false, true, true] [(), (), (), (), (), (), (), (), (), ()] 

However, using iterators is considered uniomatic (not to mention obfuscation) - an idiomatic way would be to use a for loop:

 fn main() { let mut arr = [false; 10]; for b in &mut arr { *b = rand::random(); } println!("{:?}", arr); } 
 [false, true, true, true, false, false, true, false, true, false] 

Much better. Of course, in this particular case, my first example is probably the way to go.

+5
source

Source: https://habr.com/ru/post/1259273/


All Articles