Issue #17016 has been updated by duerst (Martin D=FCrst).


mame (Yusuke Endoh) wrote in #note-39:
> This ticket was discussed in the dev meeting, but no conclusion was reach=
ed.
> =

> BTW, Mathematica's "Accumulate" is different from this proposal. It is no=
t general but specific to Plus.
> =

> https://reference.wolfram.com/language/ref/Accumulate.html
> =

> > Accumulate[list] is effectively equivalent to FoldList[Plus,list].

That's true.

> Thus, FoldList is more suitable name than Accumulate in this case.
> =

> https://reference.wolfram.com/language/ref/FoldList.html

I don't thinks FoldList would be appropriate in Ruby. I think if we use tha=
t name, it would be `fold_list`. But we are not dealing with lists, we are =
dealing with Arrays and Enumerables. But we wouldn't use `fold_array`, and =
reducing this to `fold` only wouldn't be appropriate, because fold is a muc=
h more general operation (in general, it's closer to Ruby's `inject`).


> The use case explained in #18 is not so convincing that it deserves a bui=
lt-in feature. To make something built-in, one should show that it is so fr=
equently written, and/or that it is difficult to work around. We are not su=
re that retaining a historical context is a very frequent code pattern (@mr=
kn said that cumulative sum is actually often used in mathematics, but othe=
r use case than cumulative sum was not clear).

Even if it's only cumulative sum, that's still quite useful. And if the cum=
ulative sum is the main use case, `accumulate` may not be such a bad name. =
Even if this were e.g. for products, `accumulate` would still work in some =
sense. Another name might be `trace`, i.e. in the sense of tracing the evol=
ution of a calculation.

As mentioned above, that's very relevant in a lazy context. A good example =
might be a bank account with a stream of transfers.

> And Eregon's workaround in #9 looks very simple (maybe even simpler than =
scan_left).

I agree that this doesn't feel very Ruby-ish. For me it's not so much the a=
ssignment in the block, but the initialization of a variable outside the bl=
ock.



----------------------------------------
Feature #17016: Enumerable#accumulate
https://bugs.ruby-lang.org/issues/17016#change-91709

* Author: parker (Parker Finch)
* Status: Open
* Priority: Normal
----------------------------------------
## Proposal

UPDATE: Changed proposed method name from `#scan_left` to `#accumulate`.

Add an `#accumulate` method to `Enumerable`.

## Background

`#accumulate` is similar to `#inject`, but it accumulates the partial resul=
ts that are computed. As a comparison:
```
[1, 2, 3].inject(0, &:+) =3D> 6
[1, 2, 3].accumulate(0, &:+) =3D> [0, 1, 3, 6]
```

Notably, the `accumulate` operation can be done lazily since it doesn't req=
uire processing the entire collection before computing a value.

I recently described `#accumulate`, and its relationship to `#inject`, more=
 thoroughly in [this blog post](https://medium.com/building-panorama-educat=
ion/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00).

## Reasoning
We heavily rely on the accumulate operation. We use an [event-sourcing](htt=
ps://martinfowler.com/eaaDev/EventSourcing.html) pattern, which means that =
we are scanning over individual "events" and building up the corresponding =
state. We rely on the history of states and need to do this lazily (we stre=
am events because they cannot fit in memory). Thus the scan operation is mu=
ch more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan op=
eration. [This question](https://stackoverflow.com/questions/1475808/cumula=
tive-array-sum-in-ruby) would be more easily answered by `#accumulate`. It =
is a natural fit for any application that needs to store the incrementally-=
computed values of an `#inject`, and a requirement for an application that =
needs to use `#inject` while maintaining laziness.

## Implementation
There is a Ruby implementation of this functionality [here](https://github.=
com/panorama-ed/scan_left/) and an implementation in C [here](https://githu=
b.com/ruby/ruby/pull/3078).

Update: @nobu has provided an alternative implementation [here](https://git=
hub.com/ruby/ruby/pull/1972).

## Counterarguments
Introducing a new public method is committing to maintenance going forward =
and expands the size of the Ruby codebase -- it should not be done lightly.=
 I think that providing the functionality here is worth the tradeoff, but I=
 understand any hesitation to add yet more to Ruby!

---Files--------------------------------
scan_left_example.rb (2.93 KB)


-- =

https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>