Hacker News new | ask | show | jobs
by onetoo 436 days ago

  > Even more annoying is that I have to duplicate the iterator code: as I often work with frames that may be flipped bottom-up I want to write code like
  >
  >    let mut iterator = if !flipped {
  >       data.chunks_mut(stride)
  >    } else {
  >       data.chunks_mut(stride).rev()
  >    };
  >    for line in iterator { ... }
  >
  > but I can’t since objects have different type (and probably size) and there’s no realistic way to coerce them to the same interface.
For this specific case there is a relatively ergonomic solution using dynamic trait objects + temporary lifetime extensions, available since Rust 1.79:

  let iterator: &mut dyn Iterator<Item = _> = if !flipped {
    &mut data.into_iter()
  } else {
    &mut data.into_iter().rev()
  };
  for line in iterator { ... }
Alternatively, if this is not a feasible solution (e.g. we want to return the new iterator to an outer scope, or the overhead of dyn indirection is unacceptable in this context), one can consider using itertools::Either instead:

  use itertools::Either;
  fn conditionally_flip_iter<I: DoubleEndedIterator>(
      data: I,
      flipped: bool,
  ) -> impl Iterator<Item = I::Item> {
      if !flipped {
          Either::Left(data.into_iter())
      } else {
          Either::Right(data.into_iter().rev())
      }
  }
  // ...
  let mut iterator = conditionally_flip_iter(data, flipped);
  for line in iterator { ... }
1 comments

Another approach:

  let mut iterator = data.chunks_mut(stride);
  while let Some(line) = if !flipped { iterator.next() } else { iterator.next_back() } {
      …
  }
I sometimes wonder idly if the language would have been better off without a `for` loop (if `while let` had happened much earlier). `while let` is more verbose, mainly because iterator construction has to be an explicit separate line, but it’s also more amenable to alteration to make it more fit for purpose. (You can go down to `loop` and `break`, but I think this sacrifices too much in ergonomics and comprehensibility in the usual case. As `while let` also compromises, but I wonder if it’s closer to the sweet spot than commonly imagined, and `for` doesn’t actually get you so much.)