3

Simple question, is it possible to do a for loop on a range of negative values? Specifically starting at -1 and iterating down to some negative value. for i in -1..x apparently isn't kosher.

Other than the ugly solution of iterating on the absolute values and then applying the sign within the loop.

herpderp
  • 15,819
  • 12
  • 42
  • 45
  • Does this answer your question? [How to make a reverse ordered for loop?](https://stackoverflow.com/questions/25170091/how-to-make-a-reverse-ordered-for-loop) – Herohtar Mar 06 '22 at 02:58

2 Answers2

2

The problem isn't in the negative numbers, the problem is in the reverse range. If we assume that x < -1 then you have a range (a,b) with a > b.

The default step of a rust range in a for loop is +1, so the loop never executes. If you write it out, C++ style, you'd be saying

for (i=-1; i < x; i++) { ... }

So what you want to do is reverse the range:

for i in (x..=-1).rev()

EDIT: Because (x..-1) does not include -1, we need to change it to (x..=-1). In that case the range will include both x and 1. If we don't want that, we have to fiddle with the x bound as well, e.g. ((x+1)..=-1).rev

cadolphs
  • 9,014
  • 1
  • 24
  • 41
2

The standard Range type (what you get with a..b) is a half-open increasing range. If you have a range where a >= b, then the range is empty.

If you want to iterate a range in reverse (decreasing) order, then you need to use Iterator::rev to reverse the range, which is enabled by range being a DoubleEndedIterator and providing the reverse iteration next_back.

So in this case, you'd iterate over ((x + 1)..0).rev().

Just as a fun side note, you can also get basically any iterator you want out of iter::successors, by just providing a fn next(&T) -> Option<T>; in this case, |x| x - 1, if that's clearer in a specific use case than reversing an increasing range.

CAD97
  • 1,160
  • 12
  • 29