summaryrefslogtreecommitdiffstats
path: root/Modules/_functoolsmodule.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2006-08-26 20:49:04 (GMT)
committerGuido van Rossum <guido@python.org>2006-08-26 20:49:04 (GMT)
commit0919a1a07b061ef9a8a94cc1d92c1895b00967cb (patch)
tree812681b0b579aa36b1117b192c016b7f90ada6b0 /Modules/_functoolsmodule.c
parent6a2a2a08329567ea41f4f073cb43e487f83872c7 (diff)
downloadcpython-0919a1a07b061ef9a8a94cc1d92c1895b00967cb.zip
cpython-0919a1a07b061ef9a8a94cc1d92c1895b00967cb.tar.gz
cpython-0919a1a07b061ef9a8a94cc1d92c1895b00967cb.tar.bz2
Part of SF patch #1513870 (the still relevant part) -- add reduce() to
functools, and adjust docs etc.
Diffstat (limited to 'Modules/_functoolsmodule.c')
-rw-r--r--Modules/_functoolsmodule.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 7b23210..1b363fc 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -242,12 +242,88 @@ static PyTypeObject partial_type = {
};
+/* reduce (used to be a builtin) ********************************************/
+
+static PyObject *
+functools_reduce(PyObject *self, PyObject *args)
+{
+ PyObject *seq, *func, *result = NULL, *it;
+
+ if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
+ return NULL;
+ if (result != NULL)
+ Py_INCREF(result);
+
+ it = PyObject_GetIter(seq);
+ if (it == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "reduce() arg 2 must support iteration");
+ Py_XDECREF(result);
+ return NULL;
+ }
+
+ if ((args = PyTuple_New(2)) == NULL)
+ goto Fail;
+
+ for (;;) {
+ PyObject *op2;
+
+ if (args->ob_refcnt > 1) {
+ Py_DECREF(args);
+ if ((args = PyTuple_New(2)) == NULL)
+ goto Fail;
+ }
+
+ op2 = PyIter_Next(it);
+ if (op2 == NULL) {
+ if (PyErr_Occurred())
+ goto Fail;
+ break;
+ }
+
+ if (result == NULL)
+ result = op2;
+ else {
+ PyTuple_SetItem(args, 0, result);
+ PyTuple_SetItem(args, 1, op2);
+ if ((result = PyEval_CallObject(func, args)) == NULL)
+ goto Fail;
+ }
+ }
+
+ Py_DECREF(args);
+
+ if (result == NULL)
+ PyErr_SetString(PyExc_TypeError,
+ "reduce() of empty sequence with no initial value");
+
+ Py_DECREF(it);
+ return result;
+
+Fail:
+ Py_XDECREF(args);
+ Py_XDECREF(result);
+ Py_DECREF(it);
+ return NULL;
+}
+
+PyDoc_STRVAR(functools_reduce_doc,
+"reduce(function, sequence[, initial]) -> value\n\
+\n\
+Apply a function of two arguments cumulatively to the items of a sequence,\n\
+from left to right, so as to reduce the sequence to a single value.\n\
+For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
+((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
+of the sequence in the calculation, and serves as a default when the\n\
+sequence is empty.");
+
/* module level code ********************************************************/
PyDoc_STRVAR(module_doc,
"Tools that operate on functions.");
static PyMethodDef module_methods[] = {
+ {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
{NULL, NULL} /* sentinel */
};