In spare moments, I've been plugging away at making various functions work nice with iterators (map, min, max, etc). Over and over this requires writing code of the form: op2 = PyIter_Next(it); if (op2 == NULL) { /* StopIteration is *implied* by a NULL return from * PyIter_Next() if PyErr_Occurred() is false. */ if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); else goto Fail; } break; } 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) { PyObject *result; if (!PyIter_Check(iter)) { PyErr_Format(PyExc_TypeError, "'%.100s' object is not an iterator", iter->ob_type->tp_name); *error = 1; return NULL; } result = (*iter->ob_type->tp_iternext)(iter); *error = 0; if (result) return result; if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); else *error = 1; } /* Else StopIteration is implicit, and there is no error. */ return NULL; } Then *calls* could be the simpler: op2 = PyIter_Next(it, &error); if (op2 == NULL) { if {error) goto Fail; break; } 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). 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.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4