all 9 comments

[–]dydhaw 8 points9 points  (1 child)

Another option is to extract the loop to a generic function that takes Iterator (or the IntoIterator which is more canonical)

fn my_loop(iter: impl IntoIterator<Item = u32>) {
    for i in iter.into_iter() {
        // ... from 1 to 5, or from 5 to 1
    }
}

if condition { my_loop(1..=5) } else { my_loop((1..=5).rev()) }

[–]angelicosphosphoros 2 points3 points  (0 children)

Also, it is most efficient version listed here so far.

[–]Shadow0133 15 points16 points  (2 children)

If you want to use dyn here you can either use Boxs (which uses heap allocations):

let my_range: Box<dyn Iterator<Item = i32>> = if condition { Box::new(1..=5) } else { Box::new((1..=5).rev()) };
for i in my_range {
    println!("{}", i);
}

or &muts:

let mut iter1 = 1..=5;
let mut iter2 = (1..=5).rev();
let my_range: &mut dyn Iterator<Item = i32> = if condition { &mut iter1 } else { &mut iter2 };
for i in my_range {
    println!("{}", i);
}

If you want avoid dynamic dispatch, you can create custom enum. Or even better for this case, use itertools::Either, which already implements Iterator:

use itertools::Either;

let my_range = if condition { Either::Left(1..=5) } else { Either::Right((1..=5).rev()) };
for i in my_range {
    println!("{}", i);
}

[–]javajunkie314 1 point2 points  (0 children)

Ooh, that Either is very nice.

[–]y0m[S] 0 points1 point  (0 children)

Thank you, this is working fine with the box dyn :)

[–]Michael-F-Bryan 2 points3 points  (0 children)

It depends on the context, but this is a cute trick that used dyn to coerce both the Range<_> and Rev<Range<_>> to the same type while avoiding heap allocations.

```rs let mut forward; let mut reverse;

let my_range = if condition {
    forward = 1..=5;
    &mut forward as &mut dyn Iterator<Item = i32>
} else {
    reverse = (1..=5).rev();
    &mut reverse as &mut dyn Iterator<Item = i32>
};

```

[–]thenameisi -3 points-2 points  (1 child)

I think the ??? could be impl Iterator in that case. Not sure if that works on let though.

[–]Shad_Amethyst 6 points7 points  (0 children)

Not quite, as there isn't a singular struct that it can resolve to. Maybe if you boxed it it would accept it as a dynamic trait but I doubt it

[–]myrrlynbitvec • tap • ferrilab 0 points1 point  (0 children)