/* reduce (used to be a builtin) ********************************************/
-// Not converted to argument clinic, because of `args` in-place modification.
-// AC will affect performance.
+/*[clinic input]
+_functools.reduce
+
+ function as func: object
+ iterable as seq: object
+ initial as result: object = NULL
+ /
+
+Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
+
+This effectively reduces the iterable to a single value. If initial is present,
+it is placed before the items of the iterable in the calculation, and serves as
+a default when the iterable is empty.
+
+For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
+calculates ((((1 + 2) + 3) + 4) + 5).
+[clinic start generated code]*/
+
static PyObject *
-functools_reduce(PyObject *self, PyObject *args)
+_functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
+ PyObject *result)
+/*[clinic end generated code: output=30d898fe1267c79d input=d233c2670cba7f66]*/
{
- PyObject *seq, *func, *result = NULL, *it;
+ PyObject *args, *it;
- if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
- return NULL;
if (result != NULL)
Py_INCREF(result);
return NULL;
}
-PyDoc_STRVAR(functools_reduce_doc,
-"reduce(function, iterable[, initial], /) -> value\n\
-\n\
-Apply a function of two arguments cumulatively to the items of an iterable, from left to right.\n\
-\n\
-This effectively reduces the iterable to a single value. If initial is present,\n\
-it is placed before the items of the iterable in the calculation, and serves as\n\
-a default when the iterable is empty.\n\
-\n\
-For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])\n\
-calculates ((((1 + 2) + 3) + 4) + 5).");
-
/* lru_cache object **********************************************************/
/* There are four principal algorithmic differences from the pure python version:
"Tools that operate on functions.");
static PyMethodDef _functools_methods[] = {
- {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
+ _FUNCTOOLS_REDUCE_METHODDEF
_FUNCTOOLS_CMP_TO_KEY_METHODDEF
{NULL, NULL} /* sentinel */
};
return return_value;
}
+PyDoc_STRVAR(_functools_reduce__doc__,
+"reduce($module, function, iterable, initial=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Apply a function of two arguments cumulatively to the items of an iterable, from left to right.\n"
+"\n"
+"This effectively reduces the iterable to a single value. If initial is present,\n"
+"it is placed before the items of the iterable in the calculation, and serves as\n"
+"a default when the iterable is empty.\n"
+"\n"
+"For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])\n"
+"calculates ((((1 + 2) + 3) + 4) + 5).");
+
+#define _FUNCTOOLS_REDUCE_METHODDEF \
+ {"reduce", _PyCFunction_CAST(_functools_reduce), METH_FASTCALL, _functools_reduce__doc__},
+
+static PyObject *
+_functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
+ PyObject *result);
+
+static PyObject *
+_functools_reduce(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *seq;
+ PyObject *result = NULL;
+
+ if (!_PyArg_CheckPositional("reduce", nargs, 2, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ seq = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ result = args[2];
+skip_optional:
+ return_value = _functools_reduce_impl(module, func, seq, result);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_functools__lru_cache_wrapper_cache_info__doc__,
"cache_info($self, /)\n"
"--\n"
return return_value;
}
-/*[clinic end generated code: output=755265bb6d5ea751 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=214d6c6307cfcd91 input=a9049054013a1b77]*/