Ecco una macro che fa il lavoro:
#![feature(macro_rules)]
macro_rules! product(
($first:ident, $($next:ident),*) => (
$first.iter() $(
.flat_map(|e| std::iter::Repeat::new(e)
.zip($next.iter()))
)*
);
)
fn main() {
let a = ['A', 'B', 'C'];
let b = [1i, 4];
let c = [true, false];
let d = ['x', 'y'];
for (((a, b), c), d) in product![a, b, c, d] {
println!("{} {} {} {}", a, b, c, d);
}
}
uscita:
A 1 true x
A 1 true y
A 1 false x
A 1 false y
A 4 true x
A 4 true y
etc...
Playpen example
La macro restituisce il seguente
a.iter()
.flat_map(|e| std::iter::Repeat::new(e).zip(b.iter()))
.flat_map(|e| std::iter::Repeat::new(e).zip(c.iter()))
.flat_map(|e| std::iter::Repeat::new(e).zip(d.iter()))
flat_map(|e| ...)
combina una sequenza di iteratori in un iteratore. Il e
è un elemento prodotto da un iteratore.
std::iter::Repeat::new(e)
crea un iteratore che si ripete e
.
.zip(...)
itera su due iteratori contemporaneamente, producendo gli elementi di entrambi in coppia.
macro sono un po 'più lungo da spiegare, quindi è meglio leggere il macro guide
non so se questo è il modo migliore per farlo.
fonte
2014-07-18 09:29:02
Penso quasi che mi aspetto che i bool siano un caso speciale, vorrei uno strumento diverso. Ma uno generico sarebbe utile per altre situazioni. In realtà, per i bool, molte persone "eseguono l'iterazione" (conteggio) su un 'std :: bitset'. –
Quello che vuoi sarebbe in Python essere ['itertools.product'] (https://docs.python.org/3/library/itertools.html#itertools.product). Implementare una cosa del genere in Rust, tuttavia, non è così facile come potrebbe sembrare a prima vista. L'implementazione in genere richiederà praticamente macro. –