I’m really confused: The standard approach in Java is to throw exceptions only in “abnormal” conditions and not to use them to signal end-of-iterator.
examples: Effective Java, item 57 (“Use exceptions only for exceptional conditions”) and JavaSpecialists newsletter 162:
Flow control
We should never cause an exception that is otherwise preventable. I have seen code where instead of checking bounds, it is assumed that the data will be correct and then RuntimeExceptions are caught:
Here is an example of bad code (please don’t code like this):
public class Antipattern1 { public static void main(String[] args) { try { int i = 0; while (true) { System.out.println(args[i++]); } } catch (ArrayIndexOutOfBoundsException e) { // we are done } } }
whereas it is standard to use this idiom in Python, e.g. StopIteration:
exception StopIteration
Raised by an iterator‘s next() method to signal that there are no further values. This is derived from Exception rather than StandardError, since this is not considered an error in its normal application.
Why is it bad for Java but good for Python?
Python and Java have vastly different approaches to exceptions. In Python, exceptions are normal. Look up EAFP (Easier to ask for forgiveness than permission) in the Python glossary. Also check what Wikipedia has to say.
StopIteration is just an example of EAFP – just go ahead and get the next thing from the iterator, and if that fails, handle the error.
If the code is more readable with a non-local exit, in Python you use an exception. You don’t write checks, you just deal with failures if things don’t work out. There’s absolutely nothing shameful about it, in fact it’s encouraged. Unlike in Java.
Now for a specific case of StopIteration: Consider generator functions.
To support some kind of
has_next()method, the generator would have to check for the next value, triggering theprintbefore the2is asked for. The value (or exception raised) would have to be remembered in the iterator. Ifhas_nextwas called twice, only the first one would trigger the side effect. Or the next value could always be precomputed, even if it’s not needed.I find Python’s semantics – computing only whenever the next value is needed – the nicest alternative.
Of course Java doesn’t have resumable generators, so it’s hard to compare here. But it’s some anecdotal evidence that StopIteration generalizes better than hasNext().