2016-11-04 24 views
5

我遇到了一個問題,我試圖用隨機的真/假值初始化布爾二維數組,但編譯器看起來不像能夠推斷我需要的類型;我只是想知道我需要指定推理引擎能夠解決這個問題。「無法推斷類型爲`_`」在地圖上使用Rust時的地圖

extern crate rand; 

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

遊樂場link(不rand::random()

我得到的錯誤是

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

那麼,你可能想閱讀關於['collect()'](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect)的文檔。一旦你明白爲什麼無法推斷閉包的返回類型,你仍然無法收集到一個大小的數組。你以後可以相應地重新提出這個問題嗎? –

+1

除了性能之外,您可能想要獲取'Rng'並重用它,而不是一遍又一遍地抓取線程本地RNG。 – Shepmaster

回答

4

由於類型[T; 10]實現Rand其中T: Rand,您可以直接使用rand::random()

extern crate rand; 

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

至於爲什麼類型推斷在你的榜樣失敗 - 這裏的東西稍微簡單說明該問題:

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

給出了錯誤:

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 

因此,我們可以指定類型:

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

請注意使用「turbo魚「運營商::<>收集後指定要收集的類型,在這種情況下爲::<[bool; 10]>。遺憾的是這裏的編譯器會抱怨:

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

那麼,什麼是std::iter::FromIterator<bool>?那麼,考慮collect函數的定義:

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

這意味着任何類型的你正在收集到需要實現FromIterator<Self::Item>。不幸的是,陣列不實施FromIterator - 但有很多可能的類型,例如Vec,VecDeque,HashSet,BTreeSet等等。因此,我們可以通過修改例如:

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

然而,這可能不會給你你所希望看到的結果:

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

那麼是什麼原因?爲什麼arr雖然被聲明爲可變,但並沒有發生變異,我們用iter_mut?原因是map產生一個新的對象從現有的 - 它不映射「就地」。如果你真的想就地映射,你可以使用以下命令:

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

屈服

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

然而,這種使用迭代器被認爲是unidiomatic(更不用提混亂) - 的慣用的方法是使用一個for循環:

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] 

好多了。當然,在這種特殊情況下,我的第一個例子可能是要走的路。

相關問題