[Python-ideas] Add nullifier argument to functools.reduce?

David Mertz mertz at gnosis.cx
Sat Aug 23 19:25:06 CEST 2014


This "nullifier" is mathematically called an "absorbing element", but
saying an "attractor" might be a little more general.  I.e. think of a
local optimization problem, where multiple local min/max points might
occur.  If you reach one, further iteration won't budge from that point,
even if it's not the "global absorbing element."

However, any such argument--including the much more useful
sentinel/'stop_on' idea--significantly changes the semantics of reduce.  In
particular, as is reduce() always consumes its iterator.  Under these
changes, it may or may not consume the iterator, depending on what elements
occur.

Given that one can easily write one's own three line wrapper
'reduce_with_attractor()' for this special semantics which hasn't been
given a use case, I can't see a point of including the argument in the
stdlib.

-1 on proposal.



On Sat, Aug 23, 2014 at 8:30 AM, Warren Weckesser <
warren.weckesser at gmail.com> wrote:

> I'd like to add an additional optional argument to functools.reduce.
> The argument is the "nullifier" of the reducing operation.  It is a value
> such that function(nullifier, anything) returns nullifier.  For example, if
> function(x, y) computes x*y, the nullifier is 0.  If function(x, y) is
> the intersection of the sets x and y, the nullifier is the empty set.
>
> The argument would allow reduce to "short circuit" its calculation.   When
> reduce encounters the nullifier, it can return immediately.  This can
> provide
> a significant improvement in performance in some cases.
>
> The change is simple.  Here, for example, is  the "rough equivalent" for
> functools.reduce from the docs:
>
>     def reduce(function, iterable, initializer=None):
>         it = iter(iterable)
>         if initializer is None:
>             try:
>                 initializer = next(it)
>             except StopIteration:
>                 raise TypeError('reduce() of empty sequence with no
> initial value')
>         accum_value = initializer
>         for x in it:
>             accum_value = function(accum_value, x)
>         return accum_value
>
> Here's how it looks with the optional nullifier argument; the only
> change is the new argument and an 'if' statement in the 'for' loop.
>
>     def reduce(function, iterable, initializer=None, nullifier=None):
>         it = iter(iterable)
>         if initializer is None:
>             try:
>                 initializer = next(it)
>             except StopIteration:
>                 raise TypeError('reduce() of empty sequence with no
> initial value')
>         accum_value = initializer
>         for x in it:
>             if nullifier is not None and accum_value == nullifier:
>                 break
>             accum_value = function(accum_value, x)
>         return accum_value
>
> (It might be better to use a distinct singleton for the default
> value of nullifier, to allow None to be a valid nullifier.)
>
> The actual implementation is in the extension module _functoolsmodule.c.
> It looks like the changes to the C code should be straightforward.
>
>
> Warren
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20140823/123aeb67/attachment.html>


More information about the Python-ideas mailing list