Ponieważ typ [T; 10]
realizuje Rand
gdzie T: Rand
, można użyć rand::random()
bezpośrednio:
extern crate rand;
fn main() {
let grid: [[bool; 10]; 10] = rand::random();
println!("{:#?}", grid);
}
Jak, dlaczego typ wnioskowanie zawodzi w Twojej przykład - oto coś nieco prostsze, który ilustruje problem:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect();
println!("{:?}", arr);
println!("{:?}", mapped);
}
daje błąd:
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
Więc możemy określić typ:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect::<[bool; 10]>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Uwaga na użycie turbosprężarki "" ryby " operator ::<>
po zebraniu, aby określić typ, w którym ma zostać zebrany, w tym przypadku ::<[bool; 10]>
. Niestety tutaj kompilator będzie narzekać:
error[E0277]: the trait bound `[_; 10]: std::iter::FromIterator<bool>` is not satisfied
Więc co jest std::iter::FromIterator<bool>
? Cóż, należy rozważyć definicję collect
funkcyjnego:
fn collect<B>(self) -> B
where B: FromIterator<Self::Item>
Oznacza to niezależnie od typu jesteś zbierając do potrzeb wdrożyć FromIterator<Self::Item>
. Tablice niestety nie implementują FromIterator
- ale istnieje wiele możliwych typów, na przykład Vec
, VecDeque
, HashSet
, BTreeSet
i tak dalej. Więc możemy zmodyfikować przykład:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect::<Vec<bool>>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Jednak to nie może dać wynik ty liczyliśmy:
[false, false, false, false, false, false, false, false, false, false]
[true, false, false, true, true, false, true, false, true, true]
więc co daje? Dlaczego arr
nie został zmutowany, mimo że został uznany za zmienny i użyliśmy iter_mut
? Powodem jest to, że map
tworzy nowy obiekt nowy - nie mapuje "w miejscu".Jeśli naprawdę chciał na mapie w miejscu, można użyć następujących:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|b| *b = rand::random()).collect::<Vec<()>>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Plonowanie
[true, false, true, true, true, false, false, false, true, true]
[(),(),(),(),(),(),(),(),(),()]
to jednak korzystanie z iteratorów jest uważany unidiomatic (nie wspominając mylące) - w idiomatyczne sposób byłoby użyć for
pętlę:
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]
Znacznie lepiej. Oczywiście w tym konkretnym przypadku moim pierwszym przykładem jest prawdopodobnie droga.
Cóż, możesz chcieć przeczytać dokumentację na ['collect()'] (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect). Gdy już zrozumiesz, dlaczego nie można wywnioskować typu powrotu zamknięcia, nadal nie możesz się połączyć w tablicę o wymiarach. Czy potrafisz odpowiednio zmienić zdanie na pytanie? –
Jako spektakl na bok, prawdopodobnie chcesz pobrać 'Rng' i ponownie użyć go, zamiast chwytać lokalny wątek RNG w kółko. – Shepmaster