[issue23049] Fix functools.reduce code equivalent.

New submission from Terry J. Reedy:
from functools import reduce def add(a,b): return a+b reduce(add, {})
Traceback (most recent call last): File "C:\Programs\Python34\tem.py", line 3, in <module> reduce(add, {}) TypeError: reduce() of empty sequence with no initial value
However, the reduce-equivalent code in the doc sets a bad example and forgets to account for empty iterators.
def reduce(function, iterable, initializer=None): it = iter(iterable) if initializer is None: value = next(it) else: ...
So it lets the StopIteration escape (a bad practice that can silently break iterators). The code should be
def reduce(function, iterable, initializer=None): it = iter(iterable) if initializer is None: try: value = next(it) except StopIteration: raise TypeError("reduce() of empty sequence with no initial value") from None else: ...
(patch coming)
---------- assignee: docs@python components: Documentation, Interpreter Core messages: 232626 nosy: docs@python, terry.reedy priority: normal severity: normal stage: needs patch status: open title: Fix functools.reduce code equivalent. type: behavior versions: Python 3.4, Python 3.5
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Changes by Raymond Hettinger raymond.hettinger@gmail.com:
---------- assignee: docs@python -> rhettinger nosy: +rhettinger
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Serhiy Storchaka added the comment:
I think it would be good to add Python implementation in functools.py and test they equivalence in tests.
---------- nosy: +serhiy.storchaka
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Terry J. Reedy added the comment:
Background: the OP of #19202 proposed equivalent code for all the functool functions, including two versions for reduce. Georg combined the two versions into the one that Raymond pushed. Both agreed that reduce was the only function that really needed this. I called Georg's code 'excellent'.
I have changed my mind slightly because people use such code equivalents not only for understanding but also as models for writing code, and because some people have had problems when by doing the same as this model, which ignores the empty iterable case.
If you do not want to 'uglify' the doc code by making it exactly equivalent, how about qualifying the claim instead? Change 'equivalent' to 'equivalent for non-empty iterables'.
---------- keywords: +patch nosy: +georg.brandl
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Raymond Hettinger added the comment:
Elsewhere I have used "rough equivalent".
FWIW, the initializer defaulting to "None" is also an approximation. It would be more technically correct to have "initializer = sentinel" where "sentinel = object()". But of course this too would obfuscate the documentation which mainly aimed to clarify two sticky points: 1) the order of arguments to the function call (accm, x) vs (x, accm) and 2) that if an initializer isn't specified, the first value from the iterable is used. These are the two issues that Guido found difficult to remember and caused reduce() to be banished from builtins.
----------
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Antoine Pitrou added the comment:
I agree with Raymond. Examples in the code are not meant to be a reference but, well, examples. That is, the educational value should come first and strict adherence to the language spec only second.
"Roughly equivalent" is already used in the functools doc, it can probably be reused :-)
---------- nosy: +pitrou
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Roundup Robot added the comment:
New changeset 0b3d69f15950 by Raymond Hettinger in branch '3.4': Issue #23049: Pure python equivalent shouldn't imply more exactitude than is really there. https://hg.python.org/cpython/rev/0b3d69f15950
---------- nosy: +python-dev
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Changes by Raymond Hettinger raymond.hettinger@gmail.com:
---------- resolution: -> fixed status: open -> closed
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________

Changes by Berker Peksag berker.peksag@gmail.com:
---------- stage: needs patch -> resolved
_______________________________________ Python tracker report@bugs.python.org http://bugs.python.org/issue23049 _______________________________________
participants (6)
-
Antoine Pitrou
-
Berker Peksag
-
Raymond Hettinger
-
Roundup Robot
-
Serhiy Storchaka
-
Terry J. Reedy