diff --git a/.release-notes/4127.md b/.release-notes/4127.md new file mode 100644 index 0000000000..dbdac65cf4 --- /dev/null +++ b/.release-notes/4127.md @@ -0,0 +1,13 @@ +## Fix for infinite Ranges + +Even though all Range objects that contain NaN parameters or a zero step parameter are considered infinite, some did not iterate at all or produced an error after the first iteration. For example, the code from the Range documentation: + +```pony + // this Range will produce 0 at first, then infinitely NaN + let nan: F64 = F64(0) / F64(0) + for what_am_i in Range[F64](0, 1000, nan) do + wild_guess(what_am_i) + end +``` + +did not run as expected, but rather produced an error on the first iteration. This is now fixed, and .next() calls on the above `Range[F64](0, 1000, nan)` now first yields 0 and subsequently indefinetely NaN values. Likewise, `Range(10, 10, 0)` will now indefinitely yield `10`. diff --git a/packages/collections/_test.pony b/packages/collections/_test.pony index 878b15465d..60d03c0295 100644 --- a/packages/collections/_test.pony +++ b/packages/collections/_test.pony @@ -652,8 +652,6 @@ class \nodoc\ iso _TestRange is UnitTest _assert_infinite[F64](h, 0, 10, p_inf) _assert_infinite[F64](h, 100, 10, n_inf) - - fun _assert_infinite[N: (Real[N] val & Number)]( h: TestHelper, min: N, @@ -663,7 +661,18 @@ class \nodoc\ iso _TestRange is UnitTest let range: Range[N] = Range[N](min, max, step) let range_str = "Range(" + min.string() + ", " + max.string() + ", " + step.string() + ")" - h.assert_true(range.is_infinite(), range_str + " should be infinite") + h.assert_true(range.is_infinite(), range_str + " should be infinite") + try + let nextval = range.next()? + h.assert_eq[N](nextval, min) + else + h.fail(range_str + ".next(): first call should not fail but should produce " + min.string()) + end + try + range.next()? + else + h.fail(range_str + ".next(): subsequent call should not fail") + end fun _assert_range[N: (Real[N] val & Number)]( h: TestHelper, diff --git a/packages/collections/range.pony b/packages/collections/range.pony index 6846ad34a8..1b22cefb40 100644 --- a/packages/collections/range.pony +++ b/packages/collections/range.pony @@ -93,6 +93,9 @@ class Range[A: (Real[A] val & Number) = USize] is Iterator[A] or ((_min > _max) and (_inc > 0)) fun has_next(): Bool => + if _infinite then + return true + end if _forward then _idx < _max else