Details
-
Bug
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
2.4.7
-
None
Description
Calling next() on an IntRange iterator returns null when hasNext returns false. As stated in a comment in the class, it should throw NoSuchElementException to adhere to the Iterator contract.
class IntRangeItrTest extends GroovyTestCase { void testItr() { def itr = (1..2).iterator() assert itr.next() == 1 assert itr.next() == 2 assert !itr.hasNext() shouldFail(NoSuchElementException) { itr.next() // null } } }
Attachments
Issue Links
- relates to
-
GROOVY-7961 ObjectRange iterator returns null instead of NoSuchElementException
- Closed
- links to
I am happy for this change, but for completeness I think we need to document an edge case that will break after this change. I think it represents a style which we'd discourage but I don't know if someone intended it at some point or perhaps people might have used it by accident. In any case I don't think it would be in wide-spread use and I think documenting it here should suffice.
Before this change the following code works without exception:
def items = (3..5).iterator() def x while (x = items.next()) { println x }
It silently falls out of the loop once the null is returned (existing behavior). This differs from most other similar collection types, e.g.:
def items = [3, 4, 5].iterator() def x while (x = items.next()) { println x }
would throw the NoSuchElementException as the new behavior will now do.
Of course the preferred approach would be to use each or if the external iterator approach is really required, something like:
while(items.hasNext()) { println items.next() }