I just found out that passing a negative step to countup is a bad idea. I thought that countup was basically equivalent to Python's range function, but it is not. In fact it is behavior is quite odd and I would almost say buggy. For example, countup(1, 10, -2) will start an infinite loop in which a nim program will generate negative numbers until you kill it! If you try to make the first argument higher than the second, and use a negative step then countup does not generate any numbers.
It seems to me that countup should either refuse to get negative steps, or it should behave as Python's range. I personally do not see much reason to have separate countup and countdown procedures. It seems that it would be more flexible to have a single "range" or "count" procedure.
BTW, I am a little surprised that nim did not copy Python's slice syntax, which lets you specify a step. It is quite surprising how often that comes in handy.
while a <= b:
yield a
inc b
, for working in both directions there's an if needed and 2 separate loops in its branches, and it's undesired because of iterator being inline, or a check in each iteration.
iterator `..|`*[S, T](a: S, b: T): T {.inline.} =
var res: T = T(a)
let d = if res < b: 1 else: -1
while res != b:
yield res
res += d
for i in 1 ..| -3: echo i
echo "-----------------"
for i in -1 ..| 3: echo i
perfectly natural that ``countup(1, 10, -2)`` is an infinite loop
+1
But there's an "up" in the name, you cannot count up from bigger to smaller.
But that is in fact my whole point! That it is weird that currently countup lets you count "down" in one and only one very particular case (when step is negative and star is < end). As a side effect, that counts down to infinity.
My point is that countup should either never let you count down, or always let you do so (in which case countup would turn into a flexible count, removing the need for the inverse, countdown).