<div dir="ltr">Ok, so it seems everyone's happy with adding an initial_value argument.  <div><br></div><div>Now, I claim that while it should be an option, the initial value should NOT be returned by default.  (i.e. the returned generator should by default yield N elements, not N+1).  </div><div><br></div><div>Example: suppose we're doing the toll booth thing, and we want to yield a cumulative sum of tolls so far.  Suppose someone already made a reasonable-looking generator yielding the cumulative sum of tolls for today:</div><div><br></div><div>def iter_cumsum_tolls_from_day(day, toll_amount_so_far):</div><div>    return accumulate(get_tolls_from_day(day, initial=<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">toll_amount_so_far</span>))</div><div><br></div><div>And now we want to make a way to get all tolls from the month.  One might reasonably expect this to work:</div><div><br></div><div>def iter_cumsum_tolls_from_month(month, <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">toll_amount_so_far</span></span>):</div><div>    for day in month:</div><div>        for cumsum_tolls in <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">iter_cumsum_tolls_from_day(day, <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">toll_amount_so_far</span> = <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">toll_amount_so_far</span></span></span>):</span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">            yield <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">cumsum_tolls</span></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">        <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">toll_amount_so_far</span> = <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">cumsum_tolls</span></span></div><div><br></div><div>But this would actually DUPLICATE the last toll of every day - it appears both as the last element of the day's generator and as the first element of the next day's generator.  </div><div><br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">This is why I think that there should be an additional "</span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;background-color:rgb(255,255,255);float:none;display:inline">include_initial_in_return=</span><wbr style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;background-color:rgb(255,255,255)"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;font-size:12.8px;background-color:rgb(255,255,255);float:none;display:inline">False" argument.  I do </span>agree that it should be an option to include the initial value (your "find tolls over time-span" example shows why), but that if you want that you should have to show that you thought about that by specifying "<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">include_initial_in_return=True"</span></div><div><br></div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 9, 2018 at 10:30 PM, Tim Peters <span dir="ltr"><<a href="mailto:tim.peters@gmail.com" target="_blank">tim.peters@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">[Tim]<br>
<span class="">>> while we have N numbers, there are N+1 slice indices.  So<br>
>> accumulate(xs) doesn't quite work.  It needs to also have a 0 inserted<br>
>> as the first prefix sum (the empty prefix sum(xs[:0]).<br>
>><br>
>> Which is exactly what a this_is_the_initial_value=0 argument would do<br>
>> for us.<br>
<br>
</span>[Greg Ewing <<a href="mailto:greg.ewing@canterbury.ac.nz">greg.ewing@canterbury.ac.nz</a>>]<br>
<span class="">> In this case, yes. But that still doesn't mean it makes<br>
> sense to require the initial value to be passed *in* as<br>
> part of the input sequence.<br>
><br>
> Maybe the best idea is for the initial value to be a<br>
> separate argument, but be returned as the first item in<br>
> the list.<br>
<br>
</span>I'm not sure you've read all the messages in this thread, but that's<br>
exactly what's being proposed.  That. e.g., a new optional argument:<br>
<br>
    accumulate(xs, func, initial=S)<br>
<br>
act like the current<br>
<br>
     accumulate(chain([S], xs), func)<br>
<br>
Note that in neither case is the original `xs` modified in any way,<br>
and in both cases the first value generated is S.<br>
<br>
Note too that the proposal is exactly the way Haskell's `scanl` works<br>
(although `scanl` always requires specifying an initial value - while<br>
the related `scanl1` doesn't allow specifying one).<br>
<br>
And that's all been so since the thread's first message, in which<br>
Raymond gave a proposed implementation:<br>
<span class=""><br>
        _sentinel = object()<br>
<br>
        def accumulate(iterable, func=operator.add, start=_sentinel):<br>
            it = iter(iterable)<br>
            if start is _sentinel:<br>
                try:<br>
                    total = next(it)<br>
                except StopIteration:<br>
                    return<br>
            else:<br>
                total = start<br>
            yield total<br>
            for element in it:<br>
                total = func(total, element)<br>
                yield total<br>
<br>
</span><span class="">> I can think of another example where this would make<br>
> sense. Suppose you have an initial bank balance and a<br>
> list of transactions, and you want to produce a statement<br>
> with a list of running balances.<br>
><br>
> The initial balance and the list of transactions are<br>
> coming from different places, so the most natural way<br>
> to call it would be<br>
><br>
>    result = accumulate(transactions, initial = initial_balance)<br>
><br>
> If the initial value is returned as item 0, then the<br>
> result has the following properties:<br>
><br>
>    result[0] is the balance brought forward<br>
>    result[-1] is the current balance<br>
><br>
> and this remains true in the corner case where there are<br>
> no transactions.<br>
<br>
</span>Indeed, something quite similar often applies when parallelizing<br>
search loops of the form:<br>
<br>
     for candidate in accumulate(chain([starting_<wbr>value], cycle(deltas))):<br>
<br>
For a sequence that eventually becomes periodic in the sequence of<br>
deltas it cycles through, multiple processes can run independent<br>
searches starting at carefully chosen different starting values "far"<br>
apart.  In effect, they're each a "balance brought forward" pretending<br>
that previous chunks have already been done.<br>
<br>
Funny:  it's been weeks now since I wrote an accumulate() that<br>
_didn't_ want to specify a starting value - LOL ;-)<br>
<div class="HOEnZb"><div class="h5">______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br></div>