2016-11-04 5 views
5

ランダムな真偽値を持つブール値の2D配列を初期化しようとしていますが、私が必要とするタイプを推論できるようにする。私は、推論エンジンがこれを解決できるように指定する必要があるのか​​不思議です。"Rustのiterでマップを使用しているときに` _`型を推論できません

extern crate rand; 

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

rand::random()なし)遊び場link

タイプ[T; 10]T: Randは、あなたが直接rand::random()を使用することができますRand実装しているので、私は取得していますエラーが

| 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

です:

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); 
} 

「ターボ魚 "オペレータ::<>収集後に収集するタイプを指定します。この場合は::<[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を実装していませんが、できるだけ多くの型があります。たとえば、VecVecDequeHashSetBTreeSetなどです。だから我々は、例を変更することができます。だから何が与える

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

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

しかし、これはあなたが望んでいた結果が得られない可能性がありますか?なぜ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); 
} 

しかし、イテレータのこの使用は、(混乱言及していない)unidiomatic考えられている

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

降伏します - 慣用的な方法は、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] 

さらに優れています。もちろん、この特定のケースでは、私の最初の例は、おそらく行く方法です。

関連する問題