[Python-Dev] Change to PyIter_Next()?

Guido van Rossum guido@digicool.com
Fri, 04 May 2001 17:03:36 -0500


> In spare moments, I've been plugging away at making various functions work
> nice with iterators (map, min, max, etc).

For which efforts I extend my greatest thanks!

> Over and over this requires writing code of the form:
> 
[etc.]
> 
> This is wordy, obscure, and in my experience is needed every time I call
> PyIter_Next().
> 
> So I'd like to hide this in PyIter_Next instead, like so:
> 
> /* Return next item.
>  * If an error occurs, return NULL and set *error=1.
>  * If the iteration terminated normally, return NULL and set *error=0.
>  * Else return the next object and set *error=0.
>  */
> PyObject *
> PyIter_Next(PyObject *iter, int *error)
> {
[etc.]
> }

> Then *calls* could be the simpler:
> 
> 	op2 = PyIter_Next(it, &error);
> 	if (op2 == NULL) {
> 		if {error)
> 			goto Fail;
> 		break;
> 	}

I originally had this API for tp_iternext, and changed it to the
current API because I got tired of having to declare the error
variable.

How about making PyIter_Next() call PyErr_Clear() when the exception
is StopIteration?

Then calls could be

    op2 = PyIter_Next(it);
    if (op2 == NULL) {
        if (PyErr_Occurred())
            goto Fail;
        break;
    }

This is a tad slower and arguably generates more code (assuming an
extra call is slower than passing an extra argument and loading it)
but doesn't require declaring the error variable.

But since you're the customer, it's your choice.

> Objections?  So far I'm almost the only user of PyIter_Next(); the only other
> use is in ceval's FOR_ITER, which goes thru a similar dance.
> 
> However, I'm not clear on why FOR_ITER doesn't clear the exception if
> PyErr_Occurred() and PyErr_ExceptionMatches(PyExc_StopIteration) are both
> true -- that sure smells like a bug (but, if so, the change above would
> squash it by magic).

Smells like a bug indeed.

> Note that I'm not proposing to change the signature of the tp_iternext slot
> similarly.  PyIter_Next() is a (IMO appropriately) higher-level function.

Agreed.

--Guido van Rossum (home page: http://www.python.org/~guido/)