Da der Typ [T; 10]
implementiert Rand
wo T: Rand
, können Sie rand::random()
direkt verwenden:
extern crate rand;
fn main() {
let grid: [[bool; 10]; 10] = rand::random();
println!("{:#?}", grid);
}
Was, warum Typinferenz in Ihrem Beispiel versagt - hier ist etwas, etwas einfacher, die das Problem veranschaulicht:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Gibt den Fehler:
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 können wir die Art angeben:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect::<[bool; 10]>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Beachten Sie die Verwendung des "Turbo Fisch " Betreiber ::<>
nach sammeln, um die Art zu sammeln, in diesem Fall ::<[bool; 10]>
. Leider wird der Compiler beschweren:
error[E0277]: the trait bound `[_; 10]: std::iter::FromIterator<bool>` is not satisfied
Also, was ist std::iter::FromIterator<bool>
? Nun betrachten wir die collect
Funktion Definition:
fn collect<B>(self) -> B
where B: FromIterator<Self::Item>
Das bedeutet, unabhängig von der Art Sie in Bedürfnisse sammeln FromIterator<Self::Item>
zu implementieren. Arrays implementieren leider nicht FromIterator
- aber es gibt viele mögliche Typen, die das tun, zum Beispiel Vec
, , HashSet
, BTreeSet
und so weiter. So können wir das Beispiel ändern:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|_| rand::random()).collect::<Vec<bool>>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Allerdings könnte dies nicht geben Sie das Ergebnis Sie erhofft hatten:
[false, false, false, false, false, false, false, false, false, false]
[true, false, false, true, true, false, true, false, true, true]
Also, was soll das? Warum wurde die arr
nicht mutiert, obwohl sie als veränderbar deklariert wurde, und wir verwendeten iter_mut
? Der Grund ist, dass map
ein neues Objekt aus dem bestehenden Objekt erzeugt - es wird nicht "in-place" abgebildet.Wenn Sie wirklich an Ort und Stelle kartieren wollte, Sie könnte verwenden Sie die folgende:
fn main() {
let mut arr = [false; 10];
let mapped = arr.iter_mut().map(|b| *b = rand::random()).collect::<Vec<()>>();
println!("{:?}", arr);
println!("{:?}", mapped);
}
Nachgeben
[true, false, true, true, true, false, false, false, true, true]
[(),(),(),(),(),(),(),(),(),()]
jedoch diese Verwendung von Iteratoren wird unidiomatic betrachtet (nicht zu erwähnen verwirrend) - die
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]
: idiomatische Weise eine
for
Schleife zu verwenden, wäre
Viel besser. Natürlich ist mein erstes Beispiel in diesem speziellen Fall wahrscheinlich der richtige Weg.
Nun, vielleicht möchten Sie die Dokumentation zu ['collect()'] (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect) lesen. Sobald Sie verstehen, warum der Rückgabetyp des Abschlusses nicht abgeleitet werden kann, können Sie immer noch nicht in einem großen Array sammeln. Kannst du die Frage danach anders formulieren? –
Als eine Leistung beiseite, möchten Sie wahrscheinlich ein 'Rng' greifen und es wiederverwenden, anstatt den thread-lokalen RNG immer wieder zu greifen. – Shepmaster