Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-7960

IntRange iterator returns null instead of NoSuchElementException

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 2.4.7
    • 2.5.0-alpha-1
    • 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

          Activity

            paulk Paul King added a comment - - edited

            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() }
            
            paulk Paul King added a comment - - edited 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() }

            Merged PR from jt1796.

            jwagenleitner John Wagenleitner added a comment - Merged PR from jt1796 .

            People

              jwagenleitner John Wagenleitner
              jwagenleitner John Wagenleitner
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: