I wish to create an iterator which yields even numbers from a value in reverse order.
This program demonstrates the issue. It reads two integers from command line and prints even numbers between them in decreasing order. It is sufficient to expect min value to be even.
use std::io::{self, BufRead};
fn main() {
// Read numbers
let mut input = io::BufReader::new(io::stdin());
let mut buf = String::new();
input.read_line(&mut buf).unwrap();
let mut split = buf.split(" ");
let min = split.next().unwrap().trim().parse::<i64>().unwrap();
let max = split.next().unwrap().trim().parse::<i64>().unwrap();
// Attempt to generate the iterator
let payload: String = (min..max)
.rev()
.step_by(2)
.map(|x| x.to_string() + " ")
.collect();
println!("{payload}");
}
However, for example input of 2 6, program yields 5 3 when I would expect the numbers to be 4 2.
What is the way to create an iterator which would here produce 4 2 as unreversed version does yield 2 4?
step_by(2)works under the assumption of an iterator that strictly alternates even and odd numbers, but also starts with an even number. That's true for aRangethat starts with an even number, but not true for the reversal of everyRange. In particular, the first element of(2..6).rev()is odd.To accommodate reversed ranges that might start with odd numbers, use
skip_while:(2..6).rev()starts with5, but(2..6).rev().skips_while(...)starts with4. Note that(2..5).rev()and(2..5).rev().skips_while(...)would be equivalent, as nothing from the original iterator is skipped.Regarding efficiency, the predicate will be applied to at most 2 elements in order to satisfy the precondition required for
step_by(2), compared towhich can't use any information about the structure of
(2..6).rev()to apply the given predicate fewer than O(n) times.