The following code attempts to chain two iterators together.
fn main() {
let height = 3;
let width = 4;
let horizontal = (0..height).map(|row| {let rw = row * width; rw..rw + width});
horizontal.for_each(|x| { print!("("); x.for_each(|x|print!(" {:?} ", x)); println!(")");});
let vertical = (0..width).map(|col| (0..height).map(move |n| col + n * width));
vertical.for_each(|x| { print!("("); x.for_each(|x|print!(" {:?} ", x)); println!(")");});
let all = horizontal.chain(vertical);
//all.for_each(|x| { print!("("); x.for_each(|x|print!(" {:?} ", x)); println!(")");});
}
But the compiler complains about mismatched types.
error[E0271]: type mismatch resolving `<Map<std::ops::Range<{integer}>, [closure@src/main.rs:6:35: 6:82]> as IntoIterator>::Item == std::ops::Range<{integer}>`
--> src/main.rs:8:26
|
8 | let all = horizontal.chain(vertical);
| ^^^^^ expected struct `Map`, found struct `std::ops::Range`
|
= note: expected type `Map<std::ops::Range<{integer}>, [closure@src/main.rs:6:57: 6:81]>`
found struct `std::ops::Range<{integer}>`
The signature of chain is:
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>ⓘ where
U: IntoIterator<Item = Self::Item>
Both iterators have as Item type an Iterator with the same Item type, which admittedly is not quite what the signature demands. But I can call for example .for_each(|x| { print!("("); x.for_each(|x|print!(" {:?} ", x)); println!(")");}) on each iterator, so why can't I construct the chain to call it on the chain? Is there another way to remove such code duplication?
for_each()is evilchain(),for_each()is preferred (more performant) - but the OP uses it before.map()andcollect()to replacefor_each()is far more evil than just usingfor_each(). It's a nice trick, butfor_eachis there for a reason, and while I can immediately understand what a code withfor_each()does (even if it's unpleasant to the eye), I'll have to take a second look on your version.