Issue1492

classification
Title: Jython not handling Java Iterators properly.
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.5
process
Status: closed Resolution: invalid
Dependencies: Superseder:
Assigned To: Nosy List: fwierzbicki, juneau001, leosoto, xlorepdarkhelm, zyasoft
Priority: high Keywords:

Created on 2009-10-22.17:20:48 by xlorepdarkhelm, last changed 2014-05-22.01:08:22 by zyasoft.

Messages
msg5256 (view) Author: Cliff Hill (xlorepdarkhelm) Date: 2009-10-22.17:20:46
It appears that Jython isn't handling Java Iterators out of the box.

I built a Java class that emulates a Jython List. With it, I included a hand-tailored 
Iterator, as shown below:

    /**
     * A forward-facing iterator for the Array.
     *
     * @author darkhelm
     */
    public class Iter implements Iterator<Element> {
        /**
         * The actual iterator, able to go forward or backward.
         */
        private ListIterator<Element> iter = arr.listIterator();
       
        /**
         * @return the actual iterator that is used.
         */
        protected ListIterator<Element> getIter() {
            return iter;
        }
       
        /* (non-Javadoc)
         * @see java.util.Iterator#hasNext()
         */
        @Override
        public boolean hasNext() {
            return getIter().hasNext();
        }

        /* (non-Javadoc)
         * @see java.util.Iterator#next()
         */
        @Override
        public Element next() {
            try {
                return getIter().next();
            } catch(NoSuchElementException e) {
                return null;
            }
        }

        /**
         * @return the next element from the iterator.
         */
        public Element __iternext__() {
            return next();
        }
       
        /* (non-Javadoc)
         * @see java.util.Iterator#remove()
         */
        @Override
        public void remove() {
            getIter().remove();
        }
    }

Now, when I use the following Python code, it works perfectly fine (and doesn't use the 
iterator at all):

for pos in range(len(arr)):
    count[arr[pos]] += 1

But this is rather ugly. I am using the index of one list, to look up the value of that list 
and use it as the index of a second list. The two lists are "arr" and "count", both are 
instances of my Java class that emulates a Jython list.

Now, if I try a cleaner piece of code where I just iterate over my arr instance instead:

for val in arr:
    count[val] += 1

It breaks. It appears that the iterator isn't being handled properly... under closer 
investigation, I found that for my Iterator above, I am able to change what kind of error is 
produced by modifying the next() method. The below code will produce a 
"java.lang.NullPointerException()" exception:

        /* (non-Javadoc)
         * @see java.util.Iterator#next()
         */
        @Override
        public Element next() {
            try {
                return getIter().next();
            } catch(NoSuchElementException e) {
                return null;
            }
        }

While the code below will produce a "java.lang.NoSuchElementException()" exception:

        /* (non-Javadoc)
         * @see java.util.Iterator#next()
         */
        @Override
        public Element next() {
            return getIter().next();
        }

According to the documentation from Java, the "java.lang.NoSuchElementException()" is thrown 
when an Iterator's next() method is called and there is no more elements to iterate over (it 
is how Java signals that the iterator is finished for their iterated for(Object item : 
arr){} system). When I look up how Python designates the end of an iterator, the next() 
method is supposed to return None (or null for Java, I'm assuming), which is what I tried to 
get it to do with the try/catch block in the first example.

This seems to also affect the ability to use the max() and min() functions on my Java class, 
since they rely on iterator operations as well.

The only work-around I've had is to not iterate over my Java class, which is not as elegant, 
but it works (I also had to build my own max() and min() methods for the class as I did need 
a max() and min() functionality for getting the maximum and minimum values from my class).
msg8331 (view) Author: Jim Baker (zyasoft) Date: 2014-05-04.20:25:01
Is this still an issue with this specific case? Java iterators seem to work well in practice when consumed by Jython.

If so, please produce a test case we can merge in.
msg8533 (view) Author: Jim Baker (zyasoft) Date: 2014-05-22.01:08:22
Closing bug per msg8331
History
Date User Action Args
2014-05-22 01:08:22zyasoftsetstatus: open -> closed
resolution: invalid
messages: + msg8533
2014-05-04 20:25:01zyasoftsetassignee: juneau001 ->
messages: + msg8331
2013-02-25 18:40:28fwierzbickisetversions: + Jython 2.5, - 2.5.1
2010-09-22 23:45:12juneau001setassignee: juneau001
nosy: + juneau001
2010-09-03 16:35:22zyasoftsetpriority: high
2010-08-22 22:37:32zyasoftsetnosy: + zyasoft
2009-10-25 18:38:25leosotosetnosy: + leosoto
2009-10-23 19:22:37fwierzbickisetnosy: + fwierzbicki
2009-10-22 17:20:48xlorepdarkhelmcreate