ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left
@ 2020-07-07 17:48 finch.parker
  2020-07-08  4:00 ` [ruby-core:99083] " sawadatsuyoshi
                   ` (39 more replies)
  0 siblings, 40 replies; 41+ messages in thread
From: finch.parker @ 2020-07-07 17:48 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been reported by parker (Parker Finch).

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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!



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

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99083] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
@ 2020-07-08  4:00 ` sawadatsuyoshi
  2020-07-08 14:51 ` [ruby-core:99089] " finch.parker
                   ` (38 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: sawadatsuyoshi @ 2020-07-08  4:00 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by sawa (Tsuyoshi Sawada).


What is wrong with the following?

```ruby
[1, 2, 3].inject([0]){|a, e| a << a.last + e} # => [0, 1, 3, 6]
```

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86455

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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!



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

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99089] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
  2020-07-08  4:00 ` [ruby-core:99083] " sawadatsuyoshi
@ 2020-07-08 14:51 ` finch.parker
  2020-07-09 21:33 ` [ruby-core:99102] " eregontp
                   ` (37 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-08 14:51 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


sawa (Tsuyoshi Sawada) wrote in #note-1:
> What is wrong with the following?
> 
> ```ruby
> [1, 2, 3].inject([0]){|a, e| a << a.last + e} # => [0, 1, 3, 6]
> [1, 2, 3].each_with_object([0]){|e, a| a << a.last + e} # => [0, 1, 3, 6]
> ```


Good question! Using `#inject` or `#each_with_object` cannot be done lazily. We need to pass a lazy enumerator *after* applying the fold-like operation. As a toy example, instead of `[1, 2, 3]` we can use `(1..).lazy`:
```ruby
(1..).lazy.inject([0]){|a, e| a << a.last + e} # => infinite loop
(1..).lazy.each_with_object([0]){|e, a| a << a.last + e} # => infinite loop
(1..).lazy.scan_left(0, &:+) # => Lazy enumerator
```


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86460

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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!



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

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99102] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
  2020-07-08  4:00 ` [ruby-core:99083] " sawadatsuyoshi
  2020-07-08 14:51 ` [ruby-core:99089] " finch.parker
@ 2020-07-09 21:33 ` eregontp
  2020-07-10 20:57 ` [ruby-core:99117] " finch.parker
                   ` (36 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: eregontp @ 2020-07-09 21:33 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Eregon (Benoit Daloze).


The name `scan` seems confusing at least, since it has nothing to do with `String#scan`.
And `*_left` has no precedent in Ruby.

It seems it's basically recording the history of each block call (+ the initial value), maybe a name expressing that would be good.

Do you have real-world usages you can show?
It seems kind of niche (seems expensive if the collection is large) and can easily be replaced by `each` + 2 variables (if not lazy at least).

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86476

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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!



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

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99117] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (2 preceding siblings ...)
  2020-07-09 21:33 ` [ruby-core:99102] " eregontp
@ 2020-07-10 20:57 ` finch.parker
  2020-07-11  5:46 ` [ruby-core:99121] " nobu
                   ` (35 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-10 20:57 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).

File scan_left_example.rb added

> The name `scan` seems confusing at least, since it has nothing to do with `String#scan`.
> And `*_left` has no precedent in Ruby.
> 
> It seems it's basically recording the history of each block call (+ the initial value), maybe a name expressing that would be good.

Ah sorry, I forgot to mention that the term "scan" is what this operation is typically called in functional programming (see [here](https://en.wikipedia.org/wiki/Prefix_sum#Scan_higher_order_function) for a quick overview). So that's how the name is derived. I agree that the `*_left` suffix doesn't sound very Ruby-ish, maybe just `#scan` would be better. But then we *really* have a conflict with the name of `String#scan`, thanks for pointing that out! Any thoughts on what this could be called to disambiguate that? Perhaps `#accumulate`?

> Do you have real-world usages you can show?

The most significant real-world usage that I've had it for is the one I briefly described above. The "scan" operation is a very good fit when processing streams of data changes. To really concretize it, our use case is in education data. One example is that each day we see if a student is present or absent. We use a scan over that data to count the number of absences that a student has -- a fold (i.e. `#inject` or `#reduce`) would be insufficient because the stream is lazy.

To get a small, self-contained example, I wrote up a script that uses it (and shows how other implementations of the behavior could work). That is attached, let me know if there's anything else I can do to show the usefulness here!

> It seems kind of niche (seems expensive if the collection is large) and can easily be replaced by `each` + 2 variables (if not lazy at least).

I don't think it's actually that niche! A lot of array algorithms become easier with a `scan` operation, see [this post](https://medium.com/beauty-date-stories/algorithms-how-prefix-sums-can-help-improving-operations-over-arrays-b1f8e8141668) for an example. And I don't think that it's particularly expensive -- it should be similar in cost to a `map`.

In fact, scan-like behavior (with laziness) can be implemented with `map` without *too* much trouble. ([This](https://github.com/panorama-ed/scan_left/blob/029d3ac4fa2073afa9d7da5d7932992849c235f2/lib/scan_left.rb#L49) is the heart of the ruby implementation.) But assigning to a variable inside of the block passed to `map` doesn't feel very Ruby-ish to me:
```ruby
val = 0
collection.map { |x| val = val + x }
```
feels less natural than something like
```ruby
collection.scan(&:+)
```

One of my favorite aspects of Ruby is how easy it is to write in a functional programming style, and including the `scan` operation would expand the number of use cases covered by functional methods.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86492

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99121] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (3 preceding siblings ...)
  2020-07-10 20:57 ` [ruby-core:99117] " finch.parker
@ 2020-07-11  5:46 ` nobu
  2020-07-11 17:47 ` [ruby-core:99129] " eregontp
                   ` (34 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-11  5:46 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


parker (Parker Finch) wrote in #note-2:
> Good question! Using `#inject` or `#each_with_object` cannot be done lazily. We need to pass a lazy enumerator *after* applying the fold-like operation. As a toy example, instead of `[1, 2, 3]` we can use `(1..).lazy`:
> ```ruby
> (1..).lazy.inject([0]){|a, e| a << a.last + e} # => infinite loop
> (1..).lazy.each_with_object([0]){|e, a| a << a.last + e} # => infinite loop
> (1..).lazy.scan_left(0, &:+) # => Lazy enumerator
> ```

That sounds to me like `Enumerator::Lazy` needs `#inject` and `#each_with_object` methods to me.


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86497

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99129] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (4 preceding siblings ...)
  2020-07-11  5:46 ` [ruby-core:99121] " nobu
@ 2020-07-11 17:47 ` eregontp
  2020-07-11 17:49 ` [ruby-core:99130] " eregontp
                   ` (33 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: eregontp @ 2020-07-11 17:47 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Eregon (Benoit Daloze).


parker (Parker Finch) wrote in #note-4:

Thanks for your reply, I think it will help to discuss this issue at the dev meeting.

Maybe `prefix_sum` or just `prefix` or something like that would work?
Having `sum` in it is kind of confusing though as it can be any "operation" not just `+`-ing numbers, but it seems an official "term" for it (https://en.wikipedia.org/wiki/Prefix_sum#Scan_higher_order_function).

> But assigning to a variable inside of the block passed to `map` doesn't feel very Ruby-ish to me:
> ```ruby
> val = 0
> collection.map { |x| val = val + x }
> ```

It's just my opinion, but I see nothing wrong with that (details: it could be `val += x`).
I'd even go as far as saying `each_with_object` is often less readable than using a captured variable.
I think "purely functional, not a single re-assigned variable" often introduces significant extra complexity, when Ruby is a language that embraces both functional and imperative programming.
And anyway `each_with_object` is only useful if mutating some object (typically an Array or Hash).
Again, it's just my opinion :)

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86505

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99130] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (5 preceding siblings ...)
  2020-07-11 17:47 ` [ruby-core:99129] " eregontp
@ 2020-07-11 17:49 ` eregontp
  2020-07-12  8:52 ` [ruby-core:99133] " nobu
                   ` (32 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: eregontp @ 2020-07-11 17:49 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Eregon (Benoit Daloze).


nobu (Nobuyoshi Nakada) wrote in #note-5:
> That sounds like `Enumerator::Lazy` needs `#inject` and `#each_with_object` methods to me.

A lazy `#inject` sounds useful.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86506

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99133] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (6 preceding siblings ...)
  2020-07-11 17:49 ` [ruby-core:99130] " eregontp
@ 2020-07-12  8:52 ` nobu
  2020-07-12 11:32 ` [ruby-core:99134] " eregontp
                   ` (31 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-12  8:52 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


parker (Parker Finch) wrote in #note-2:

> 
> Good question! Using `#inject` or `#each_with_object` cannot be done lazily. We need to pass a lazy enumerator *after* applying the fold-like operation. As a toy example, instead of `[1, 2, 3]` we can use `(1..).lazy`:
> ```ruby
> (1..).lazy.inject([0]){|a, e| a << a.last + e} # => infinite loop
> (1..).lazy.each_with_object([0]){|e, a| a << a.last + e} # => infinite loop
> (1..).lazy.scan_left(0, &:+) # => Lazy enumerator
> ```



Eregon (Benoit Daloze) wrote in #note-7:
> nobu (Nobuyoshi Nakada) wrote in #note-5:
> > That sounds like `Enumerator::Lazy` needs `#inject` and `#each_with_object` methods to me.
> 
> A lazy `#inject` sounds useful.

It has a backward incompatibility on the return value.
I’m afraid if it’s acceptable. 



Eregon (Benoit Daloze) wrote in #note-7:
> nobu (Nobuyoshi Nakada) wrote in #note-5:
> > That sounds like `Enumerator::Lazy` needs `#inject` and `#each_with_object` methods to me.
> 
> A lazy `#inject` sounds useful.



----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86509

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99134] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (7 preceding siblings ...)
  2020-07-12  8:52 ` [ruby-core:99133] " nobu
@ 2020-07-12 11:32 ` eregontp
  2020-07-12 23:51 ` [ruby-core:99141] " shyouhei
                   ` (30 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: eregontp @ 2020-07-12 11:32 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Eregon (Benoit Daloze).


nobu (Nobuyoshi Nakada) wrote in #note-8:
> It has a backward incompatibility on the return value.
> I’m afraid if it’s acceptable.

Right, `inject` might return anything, not necessarily an Array and so returning a "lazy Enumerator" instead will be unwanted in at least some cases.

Using the existing lazy `map` seems most natural to me:
```ruby
val = 0
p (0..).lazy.map { |x| val += x }.first(4) # => [0, 1, 3, 6]

val = 0
p [0] + (1..).lazy.map { |x| val += x }.first(3) # => [0, 1, 3, 6]
```

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86510

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99141] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (8 preceding siblings ...)
  2020-07-12 11:32 ` [ruby-core:99134] " eregontp
@ 2020-07-12 23:51 ` shyouhei
  2020-07-14 17:50 ` [ruby-core:99167] " finch.parker
                   ` (29 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: shyouhei @ 2020-07-12 23:51 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by shyouhei (Shyouhei Urabe).


It might be possible to let inject be lazy if we ignore backwards compatibility.  But how do we partially evaluate that lazy enumerator then?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86519

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99167] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (9 preceding siblings ...)
  2020-07-12 23:51 ` [ruby-core:99141] " shyouhei
@ 2020-07-14 17:50 ` finch.parker
  2020-07-14 18:20 ` [ruby-core:99168] " finch.parker
                   ` (28 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-14 17:50 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


shyouhei (Shyouhei Urabe) wrote in #note-10:
> It might be possible to let inject be lazy if we ignore backwards compatibility.  But how do we partially evaluate that lazy enumerator then?

I think this is the crux of the issue. Because `#inject` *needs* to evaluate every element in order to return a meaningful value, it can't be partially evaluated. The "scan" operation allows for partial evaluation.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86545

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99168] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (10 preceding siblings ...)
  2020-07-14 17:50 ` [ruby-core:99167] " finch.parker
@ 2020-07-14 18:20 ` finch.parker
  2020-07-15 14:33 ` [ruby-core:99177] " eregontp
                   ` (27 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-14 18:20 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


Eregon (Benoit Daloze) wrote in #note-6:
> Maybe `prefix_sum` or just `prefix` or something like that would work?
> Having `sum` in it is kind of confusing though as it can be any "operation" not just `+`-ing numbers, but it seems an official "term" for it (https://en.wikipedia.org/wiki/Prefix_sum#Scan_higher_order_function).


I agree that including "sum" in the name is confusing. I think that "prefix_sum" is just used to describe the sum operation, and if it is generalized to other operations then it is typically called "scan".

-----


Eregon (Benoit Daloze) wrote in #note-9:
> 
> Using the existing lazy `map` seems most natural to me:
> ```ruby
> val = 0
> p (0..).lazy.map { |x| val += x }.first(4) # => [0, 1, 3, 6]
> 
> val = 0
> p [0] + (1..).lazy.map { |x| val += x }.first(3) # => [0, 1, 3, 6]
> ```

It's definitely possible to use `map`! I think it is simpler to use a scan, especially if the first element needs to be included in the lazy enumerator. For example:
```ruby
(1..).lazy.scan(0, &:+)
```
would need to be:
```ruby
val = 0
[val].chain((1..).lazy.map { |x| val += x })
```
because the `+` method doesn't work with lazy enumerators.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86546

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99177] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (11 preceding siblings ...)
  2020-07-14 18:20 ` [ruby-core:99168] " finch.parker
@ 2020-07-15 14:33 ` eregontp
  2020-07-16  5:17 ` [ruby-core:99189] " mame
                   ` (26 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: eregontp @ 2020-07-15 14:33 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Eregon (Benoit Daloze).


For the name I think just `scan` would be best then.
And accept the fact it's completely unrelated to `String#scan`.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86556

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99189] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (12 preceding siblings ...)
  2020-07-15 14:33 ` [ruby-core:99177] " eregontp
@ 2020-07-16  5:17 ` mame
  2020-07-17 14:29 ` [ruby-core:99203] " finch.parker
                   ` (25 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: mame @ 2020-07-16  5:17 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by mame (Yusuke Endoh).


Is this what you want?

```
irb(main):001:0> (1..).lazy.enum_for(:inject, 0).map {|a, b| a + b }.take(10).force
=> [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
```

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86569

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99203] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (13 preceding siblings ...)
  2020-07-16  5:17 ` [ruby-core:99189] " mame
@ 2020-07-17 14:29 ` finch.parker
  2020-07-18  3:23 ` [ruby-core:99212] " nobu
                   ` (24 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-17 14:29 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


mame (Yusuke Endoh) wrote in #note-14:
> Is this what you want?
> 
> ```
> irb(main):001:0> (1..).lazy.enum_for(:inject, 0).map {|a, b| a + b }.take(10).force
> => [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
> ```

Oh interesting, I hadn't considered that approach! That is very close to the behavior of the scan operation, and might be a good way to implement it. (The only difference in behavior I see is that the first element (`0`) is not included in the resulting enumerator with this `enum_for` approach.)

Are you suggesting that we should use that approach instead of implementing a built-in `scan` method? Or is the example to clarify what the behavior of the `scan` method would be?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86582

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99212] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (14 preceding siblings ...)
  2020-07-17 14:29 ` [ruby-core:99203] " finch.parker
@ 2020-07-18  3:23 ` nobu
  2020-07-20  6:02 ` [ruby-core:99234] " matz
                   ` (23 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-18  3:23 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


parker (Parker Finch) wrote in #note-15:
> Are you suggesting that we should use that approach instead of implementing a built-in `scan` method? Or is the example to clarify what the behavior of the `scan` method would be?

As it came from the lazy `inject` approach, the former.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86592

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99234] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (15 preceding siblings ...)
  2020-07-18  3:23 ` [ruby-core:99212] " nobu
@ 2020-07-20  6:02 ` matz
  2020-07-22 17:23 ` [ruby-core:99270] " finch.parker
                   ` (22 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: matz @ 2020-07-20  6:02 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by matz (Yukihiro Matsumoto).


I don't see any real-world use-case for `scan_left`. Is there any?
In addition, the term `scan` does not seem to describe the behavior of keeping the past sequence of accumulation.
Although I know the name from the Haskell community, I don't agree with the name.

Matz.
 

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86619

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99270] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (16 preceding siblings ...)
  2020-07-20  6:02 ` [ruby-core:99234] " matz
@ 2020-07-22 17:23 ` finch.parker
  2020-07-22 18:12 ` [ruby-core:99274] " msiegel
                   ` (21 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-22 17:23 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


matz (Yukihiro Matsumoto) wrote in #note-17:
> I don't see any real-world use-case for `scan_left`. Is there any?


I think there are real-world use cases!

Would you consider converting a history of transactions into a history of account balances a valid use-case? That can be done easily with a scan. For example, if you have `transactions = [100, -200, 200]` then you can find the history of account balances with `transactions.scan_left(0, &:+) # => [0, 100, -100, 100]`.

I have described our current use case of `scan_left` [here](https://medium.com/building-panorama-education/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00). We use an event-sourced architecture where we scan over a lazy stream of events, building up the state as we go. It is important for our use case that we are able to access past states in addition to the final state.

[This post](https://medium.com/beauty-date-stories/algorithms-how-prefix-sums-can-help-improving-operations-over-arrays-b1f8e8141668) shows how it can make repeated subarray operations more efficient -- the example there is that if you have an array of values representing changes over time periods, then you can easily aggregate those into changes over different time periods using a `scan`. This post does not use `scan`, but instead has a workaround because `scan` doesn't exist:
```ruby
sums = [0]
(1..gains.length).each do |i|
  sums[i] = sums[i - 1] + gains[i - 1]
end
```
could, if `scan` was introduced, be replaced with:
```ruby
sums = gains.scan_left(0, &:+)
```

Do those use cases seem sufficient?

---

> In addition, the term `scan` does not seem to describe the behavior of keeping the past sequence of accumulation.
> Although I know the name from the Haskell community, I don't agree with the name.

I agree the name is not ideal. It is easy to get it confused with the idea of a string scanner. As you mentioned, `scan` is the name used by Haskell, but it is also used by [Scala](https://www.scala-lang.org/api/current/scala/Array.html), [Rust](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.scan), and [C++](https://en.cppreference.com/w/cpp/algorithm/inclusive_scan). So it is a widely-used term, even if it's not the best one, which makes me think that it might be good to use it.

Alternatively, what do you think about the name `accumulate`, which [Wolfram uses](https://reference.wolfram.com/language/ref/Accumulate.html)? I think it gets the idea across better than `scan`.

Are there other names you think should be considered?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86657

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99274] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (17 preceding siblings ...)
  2020-07-22 17:23 ` [ruby-core:99270] " finch.parker
@ 2020-07-22 18:12 ` msiegel
  2020-07-23  3:12 ` [ruby-core:99286] " nobu
                   ` (20 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: msiegel @ 2020-07-22 18:12 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by RubyBugs (A Nonymous).


parker (Parker Finch) wrote in #note-18:
> I agree the name is not ideal. It is easy to get it confused with the idea of a string scanner. As you mentioned, `scan` is the name used by Haskell, but it is also used by [Scala](https://www.scala-lang.org/api/current/scala/Array.html), [Rust](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.scan), and [C++](https://en.cppreference.com/w/cpp/algorithm/inclusive_scan). So it is a widely-used term, even if it's not the best one, which makes me think that it might be good to use it.
> 
> Alternatively, what do you think about the name `accumulate`, which [Wolfram uses](https://reference.wolfram.com/language/ref/Accumulate.html)? I think it gets the idea across better than `scan`.
> 
> Are there other names you think should be considered?

In keeping with the Ruby-ish collection methods that end with "-ect", how about 
* **reflect** -- the idea is to contrast with `inject`, this "reflects" all intermediate states
* **project** -- the idea is that the original `Enumerable` is "projected" in a mathematical sense into the plane defined by the stateful function that is passed in

(just my 2 cents...)

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86662

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99286] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (18 preceding siblings ...)
  2020-07-22 18:12 ` [ruby-core:99274] " msiegel
@ 2020-07-23  3:12 ` nobu
  2020-07-23 15:39 ` [ruby-core:99301] " finch.parker
                   ` (19 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-23  3:12 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


With https://github.com/ruby/ruby/pull/3337, you can
```ruby
(1..).lazy.inject(0, :+).first(10) #=> [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
```

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86675

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99301] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (19 preceding siblings ...)
  2020-07-23  3:12 ` [ruby-core:99286] " nobu
@ 2020-07-23 15:39 ` finch.parker
  2020-07-23 21:44 ` [ruby-core:99307] " annikoff
                   ` (18 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-23 15:39 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


nobu (Nobuyoshi Nakada) wrote in #note-20:
> With https://github.com/ruby/ruby/pull/3337, you can
> ```ruby
> (1..).lazy.inject(0, :+).first(10) #=> [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
> ```

Thank you for writing that nobu! That is exactly the behavior we need.

I'm worried about the backwards compatibility of changing the behavior of `#inject` on lazy enumerables. Since right now `[1,2,3].lazy.inject(:+) # => 6` I think it would be breaking to change that behavior to be `[1,2,3].lazy.inject(:+) # => #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:inject>`.

I'm also worried about `#inject` having different behavior for strict and lazy enumerables. I don't think it would be good to have `[1,2,3].inject(:+)` be different than `[1,2,3].lazy.inject(:+).force`.

Do you think your implementation could be used for a new method, whether we call it `scan` or `accumulate` or `project` or something else? I think it would be good to have consistent behavior between strict and lazy enumerables.

---

**NOTE:** For anyone who is newer to this thread and might have missed it -- you can find this behavior, with some examples, implemented in Ruby [here](https://github.com/panorama-ed/scan_left/).

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86689

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99307] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (20 preceding siblings ...)
  2020-07-23 15:39 ` [ruby-core:99301] " finch.parker
@ 2020-07-23 21:44 ` annikoff
  2020-07-24  2:30 ` [ruby-core:99310] " nobu
                   ` (17 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: annikoff @ 2020-07-23 21:44 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by y.annikov (Yakov Annikov).


I've created a PR with the implementation of `scan` and `lazy.scan` methods https://github.com/ruby/ruby/pull/3358 
Feel free to reject it but any comments are appreciated. I got a lot of fun writing this code and looking at Ruby source code.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86696

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99310] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (21 preceding siblings ...)
  2020-07-23 21:44 ` [ruby-core:99307] " annikoff
@ 2020-07-24  2:30 ` nobu
  2020-07-25  6:20 ` [ruby-core:99327] " duerst
                   ` (16 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-24  2:30 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


RubyBugs (A Nonymous) wrote in #note-19:
> In keeping with the Ruby-ish collection methods that end with "-ect", how about 
> * **`reflect`** -- the idea is to contrast with `inject`, this "reflects" all intermediate states
> * **`project`** -- the idea is that the original `Enumerable` is "projected" in a mathematical sense into the plane defined by the stateful function that is passed in

I'd like that “this "reflects" all intermediate states” part.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86698

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99327] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (22 preceding siblings ...)
  2020-07-24  2:30 ` [ruby-core:99310] " nobu
@ 2020-07-25  6:20 ` duerst
  2020-07-25  7:49 ` [ruby-core:99328] " duerst
                   ` (15 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: duerst @ 2020-07-25  6:20 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by duerst (Martin Dürst).


parker (Parker Finch) wrote in #note-21:
> nobu (Nobuyoshi Nakada) wrote in #note-20:
> > ```ruby
> > (1..).lazy.inject(0, :+).first(10) #=> [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
> > ```

> I'm worried about the backwards compatibility of changing the behavior of `#inject` on lazy enumerables. Since right now `[1,2,3].lazy.inject(:+) # => 6` I think it would be breaking to change that behavior to be `[1,2,3].lazy.inject(:+) # => #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:inject>`.
> 
> I'm also worried about `#inject` having different behavior for strict and lazy enumerables. I don't think it would be good to have `[1,2,3].inject(:+)` be different than `[1,2,3].lazy.inject(:+).force`.

I fully agree. Lazy variants of methods should only differ with respect to laziness, not anything else.


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86722

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99328] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (23 preceding siblings ...)
  2020-07-25  6:20 ` [ruby-core:99327] " duerst
@ 2020-07-25  7:49 ` duerst
  2020-07-25 10:12 ` [ruby-core:99330] " annikoff
                   ` (14 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: duerst @ 2020-07-25  7:49 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by duerst (Martin Dürst).


nobu (Nobuyoshi Nakada) wrote in #note-23:
> RubyBugs (A Nonymous) wrote in #note-19:
> > In keeping with the Ruby-ish collection methods that end with "-ect", how about 
> > * **`reflect`** -- the idea is to contrast with `inject`, this "reflects" all intermediate states
> > * **`project`** -- the idea is that the original `Enumerable` is "projected" in a mathematical sense into the plane defined by the stateful function that is passed in
> 
> I'd like that “this "reflects" all intermediate states” part.

I think this is way too generic. In the same vein, we could call it "return", because it returns all intermediate states.
Also, I think "project" isn't appropriate, because project is usually associated with a dimension reduction.

The most specific word in the above explanation is "intermediate".  I suggest we search more along these lines. An example would be something like "inject_with_intermediates".

BTW, I also checked APL, where '\' is used for what we are discussing here, and is called scan. The fact that this is included in APL shows that this is in some sense a core operation. It doesn't appear e.g. in a 1972 manual for IBM APL\360 (http://www.softwarepreservation.org/projects/apl/Manuals/APL360UsersManuals), which means it may not have been there from the start. But I found some hints in a newer document (1982, http://www.softwarepreservation.org/projects/apl/Manuals/SharpAPLManualCorrections). My guess is that the name did not come from APL (which is one of the oldest functional programming languages).

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86723

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99330] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (24 preceding siblings ...)
  2020-07-25  7:49 ` [ruby-core:99328] " duerst
@ 2020-07-25 10:12 ` annikoff
  2020-07-28 17:42 ` [ruby-core:99367] " msiegel
                   ` (13 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: annikoff @ 2020-07-25 10:12 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by y.annikov (Yakov Annikov).


y.annikov (Yakov Annikov) wrote in #note-22:
> I've created a PR with the implementation of `scan` and `lazy.scan` methods https://github.com/ruby/ruby/pull/3358 
> Feel free to reject it but any comments are appreciated. I got a lot of fun writing this code and looking at Ruby source code.

I renamed it to `reflect` for a while though I like `scan` more.
Here are examples of the behaviour of `reflect` method that I've implemented:

``` ruby
# reflect
(0...0).reflect(:+) => []
(5..10).reflect(:+) => [5, 10, 16, 23, 31, 40, 50]
(5..10).reflect { |sum, n| sum + n } => [5, 10, 16, 23, 31, 40, 50]
(5..10).reflect(1, :*) => [1, 5, 30, 210, 1680, 15120, 151200]
(5..10).reflect(1) { |product, n| product * n } => [1, 5, 30, 210, 1680, 15120, 151200]
[1, 2, 3].reflect => no block given (ArgumentError)
```

``` ruby
# lazy.reflect
(0..Float::INFINITY).lazy.reflect(:+).first(4) => [0, 0, 1, 3]
(0..Float::INFINITY).lazy.reflect(:+).first(4) => [1, 1, 2, 4]
enum = (5..10).lazy.reflect(:+) => #<Enumerator::Lazy: #<Enumerator::Lazy: 5..10>:reflect(:+)>
7.times.map { enum.next } => [5, 10, 16, 23, 31, 40, 50]
enum = (5..10).lazy.reflect(1, :*) => #<Enumerator::Lazy: #<Enumerator::Lazy: 5..10>:reflect(1, :*)>
7.times.map { enum.next } => [1, 5, 30, 210, 1680, 15120, 151200]
[1, 2, 3].lazy.reflect => no block given (ArgumentError)
```


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86725

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99367] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (25 preceding siblings ...)
  2020-07-25 10:12 ` [ruby-core:99330] " annikoff
@ 2020-07-28 17:42 ` msiegel
  2020-07-28 23:34 ` [ruby-core:99378] " duerst
                   ` (12 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: msiegel @ 2020-07-28 17:42 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by RubyBugs (A Nonymous).


To return to naming for a moment. Did I understand an interest may exist in naming that reflects a connection or duality with `inject`?

If so, might the **scan** operation find a better Ruby name in **interject**?

The idea would be to say to new learners, with zero prior context:  “the interject method has the same form as inject, but returns the stream of **intermediate** values”?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86770

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99378] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (26 preceding siblings ...)
  2020-07-28 17:42 ` [ruby-core:99367] " msiegel
@ 2020-07-28 23:34 ` duerst
  2020-07-30 19:16 ` [ruby-core:99404] " finch.parker
                   ` (11 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: duerst @ 2020-07-28 23:34 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by duerst (Martin Dürst).


RubyBugs (A Nonymous) wrote in #note-27:
> To return to naming for a moment. Did I understand an interest may exist in naming that reflects a connection or duality with `inject`?

I guess that wouldn't be a bad idea.

> If so, might the **scan** operation find a better Ruby name in **interject**?
> 
> The idea would be to say to new learners, with zero prior context:  “the `interject` method has the same form as inject, but returns the stream of **intermediate** values”?

My most immediate impression of `interject` is that it would add something between `Array` elements (e.g. `[5..8].interject(0)` #→ [5, 0, 6, 0, 7, 0, 8] or so). But the parallel to `inject` is appealing. And `inject` itself isn't really that much of a descriptive name, either.

We would have to check whether `interject` is used in other languages, and for what.

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86783

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99404] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (27 preceding siblings ...)
  2020-07-28 23:34 ` [ruby-core:99378] " duerst
@ 2020-07-30 19:16 ` finch.parker
  2020-07-31  5:47 ` [ruby-core:99410] " nobu
                   ` (10 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-07-30 19:16 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


I'd like to sum up where we're at with this discussion. Let me know if you disagree with my interpretation here!

1. There is some support for the idea of adding this method.
2. We should avoid changing the behavior of `#inject` on lazy enumerables, since it would be confusing for the lazy version of a method to have different behavior than the strict version.
3. There is concern around the name of this method. Possibilities that have been discussed are:
  * `#scan`: This name is not very intuitive for the operation and also has other meanings. However, it is used in many other programming languages.
  * `#accumulate`: This would have my vote at the moment. It suggests that something is accumulated throughout the iteration of the collection. However, it is still a very generic term.
  * `#reflect`, `#project`, `#interject`: These end in `-ect` as many Ruby/Smalltalk methods on collections do. However, they have little meaning related to the operation at hand. I agree that it would be good to show the duality between `#inject` and this operation, but I'm concerned about using an unrelated word.

I think the next steps here are to get confirmation from @matz as to whether or not he thinks this would be a good method to add to Ruby (I described some use cases in #note-18) and to decide on a name. Does that make sense?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86852

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99410] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (28 preceding siblings ...)
  2020-07-30 19:16 ` [ruby-core:99404] " finch.parker
@ 2020-07-31  5:47 ` nobu
  2020-08-10 16:47 ` [ruby-core:99545] " finch.parker
                   ` (9 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: nobu @ 2020-07-31  5:47 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by nobu (Nobuyoshi Nakada).


I found a word [traject], means to transport, transmit, or transpose.
It may (or may not) imply [trajectory]...

[traject]: https://www.dictionary.com/browse/traject
[trajectory]: https://www.dictionary.com/browse/trajectory

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-86859

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99545] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (29 preceding siblings ...)
  2020-07-31  5:47 ` [ruby-core:99410] " nobu
@ 2020-08-10 16:47 ` finch.parker
  2020-08-21 14:22 ` [ruby-core:99664] " finch.parker
                   ` (8 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-08-10 16:47 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


nobu (Nobuyoshi Nakada) wrote in #note-30:
> I found a word [traject], means to transport, transmit, or transpose.
> It may (or may not) imply [trajectory]...
> 
> [traject]: https://www.dictionary.com/browse/traject
> [trajectory]: https://www.dictionary.com/browse/trajectory

That's an interesting word that I don't know. It looks like it's archaic, so I don't think that it has much meaning anymore. That's kind of nice, since there's not a conflicting definition that people will have in their heads. However, it also doesn't have a meaning that describes what the method does.

It does have a nice symmetry with `inject` though! Curious if others have thoughts?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-87004

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99664] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (30 preceding siblings ...)
  2020-08-10 16:47 ` [ruby-core:99545] " finch.parker
@ 2020-08-21 14:22 ` finch.parker
  2020-08-29 11:41 ` [ruby-core:99769] " daniel
                   ` (7 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-08-21 14:22 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


I'd like to propose that we name this method `#accumulate`. @matz do you think that is an acceptable name?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-87148

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99769] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (31 preceding siblings ...)
  2020-08-21 14:22 ` [ruby-core:99664] " finch.parker
@ 2020-08-29 11:41 ` daniel
  2020-09-03 14:57 ` [ruby-core:99880] " finch.parker
                   ` (6 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: daniel @ 2020-08-29 11:41 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by Dan0042 (Daniel DeLorme).


`#accumulate` is good, but since [this question](https://stackoverflow.com/q/1475808) linked in the OP was asking for the "cumulative sum" ... what about `#cumulative` ? 

```ruby
[1,2,3].cumulative.sum            #=> [1,3,6]
[1,2,3].cumulative.inject(5, :*)  #=> [[5], [5,10], [5,10,30]]
[1,2,3].cumulative.select(&:odd?) #=> [[1], [1,3]]
[1,2,3].cumulative.map{ _1 * 3 }  #=> [[3], [3,6], [3,6,9]]
```

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-87281

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:99880] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (32 preceding siblings ...)
  2020-08-29 11:41 ` [ruby-core:99769] " daniel
@ 2020-09-03 14:57 ` finch.parker
  2020-11-10 14:06 ` [ruby-core:100762] " annikoff
                   ` (5 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-09-03 14:57 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


Dan0042 (Daniel DeLorme) wrote in #note-33:
> ... what about `#cumulative` ? 

Oh that's interesting! I had leapt straight to verbs since that tends to be the pattern for methods that transform enumerables, but the examples of `[1,2,3].cumulative.some_other_method` are compelling and make sense in a "it returns a cumulative enumerator" way.

I don't think it fits quite as well when a block is passed though; `[1,2,3].cumulative(0, &:+)` doesn't read as naturally to me as the imperative `#accumulate`.

I think either option is good -- although since there's a pattern of enumerable methods being named imperatively (e.g. `#map`, `#select`, `#inject`, `#drop`) I still slightly lean toward the `#accumulate` option.


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-87407

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:100762] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (33 preceding siblings ...)
  2020-09-03 14:57 ` [ruby-core:99880] " finch.parker
@ 2020-11-10 14:06 ` annikoff
  2020-11-30 14:38 ` [ruby-core:101156] " finch.parker
                   ` (4 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: annikoff @ 2020-11-10 14:06 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by y.annikov (Yakov Annikov).


parker (Parker Finch) wrote in #note-34:
> I still slightly lean toward the `#accumulate` option.

What about `#cumulate`? Does it sound natural?


----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-88407

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:101156] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (34 preceding siblings ...)
  2020-11-10 14:06 ` [ruby-core:100762] " annikoff
@ 2020-11-30 14:38 ` finch.parker
  2021-04-13 14:51 ` [ruby-core:103429] " finch.parker
                   ` (3 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2020-11-30 14:38 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


y.annikov (Yakov Annikov) wrote in #note-35:
> What about `#cumulate`? Does it sound natural?

I'm not as familiar with the verb "cumulate", so it doesn't sound as natural to me as "accumulate". But that being said, I don't think there's a huge difference between the two words, so either one could work!

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-88842

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:103429] [Ruby master Feature#17016] Enumerable#scan_left
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (35 preceding siblings ...)
  2020-11-30 14:38 ` [ruby-core:101156] " finch.parker
@ 2021-04-13 14:51 ` finch.parker
  2021-04-17  8:15 ` [ruby-core:103497] [Ruby master Feature#17016] Enumerable#accumulate mame
                   ` (2 subsequent siblings)
  39 siblings, 0 replies; 41+ messages in thread
From: finch.parker @ 2021-04-13 14:51 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by parker (Parker Finch).


I like `#accumulate`, and thank you @nobu for an implementation [here](https://github.com/ruby/ruby/pull/3361)!

Is there anything I can do to help us come to a decision on this one?

----------------------------------------
Feature #17016: Enumerable#scan_left
https://bugs.ruby-lang.org/issues/17016#change-91522

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

Add a `#scan_left` method to `Enumerable`.

(The name "scan_left" is based on Scala's scanLeft and Haskell's scanl. It seems like "scan_left" would be a ruby-ish name for  this concept, but I'm curious if there are other thoughts on naming here!)

## Background

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

Notably, the `scan_left` operation can be done lazily since it doesn't require processing the entire collection before computing a value.

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

## Reasoning
We heavily rely on the scan operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-array-sum-in-ruby) would be more easily answered by `#scan_left`. 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://github.com/ruby/ruby/pull/3078).

## 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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:103497] [Ruby master Feature#17016] Enumerable#accumulate
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (36 preceding siblings ...)
  2021-04-13 14:51 ` [ruby-core:103429] " finch.parker
@ 2021-04-17  8:15 ` mame
  2021-04-27  9:05 ` [ruby-core:103614] " duerst
  2021-04-27 15:14 ` [ruby-core:103615] " msiegel
  39 siblings, 0 replies; 41+ messages in thread
From: mame @ 2021-04-17  8:15 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by mame (Yusuke Endoh).


This ticket was discussed in the dev meeting, but no conclusion was reached.

BTW, Mathematica's "Accumulate" is different from this proposal. It is not general but specific to Plus.

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

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

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

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

The use case explained in #18 is not so convincing that it deserves a built-in feature. To make something built-in, one should show that it is so frequently written, and/or that it is difficult to work around. We are not sure that retaining a historical context is a very frequent code pattern (@mrkn said that cumulative sum is actually often used in mathematics, but other use case than cumulative sum was not clear). And Eregon's workaround in #9 looks very simple (maybe even simpler than scan_left).

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

* 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 results that are computed. As a comparison:
```
[1, 2, 3].inject(0, &:+) => 6
[1, 2, 3].accumulate(0, &:+) => [0, 1, 3, 6]
```

Notably, the `accumulate` operation can be done lazily since it doesn't require 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-education/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00).

## Reasoning
We heavily rely on the accumulate operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-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://github.com/ruby/ruby/pull/3078).

Update: @nobu has provided an alternative implementation [here](https://github.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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:103614] [Ruby master Feature#17016] Enumerable#accumulate
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (37 preceding siblings ...)
  2021-04-17  8:15 ` [ruby-core:103497] [Ruby master Feature#17016] Enumerable#accumulate mame
@ 2021-04-27  9:05 ` duerst
  2021-04-27 15:14 ` [ruby-core:103615] " msiegel
  39 siblings, 0 replies; 41+ messages in thread
From: duerst @ 2021-04-27  9:05 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by duerst (Martin Dürst).


mame (Yusuke Endoh) wrote in #note-39:
> This ticket was discussed in the dev meeting, but no conclusion was reached.
> 
> BTW, Mathematica's "Accumulate" is different from this proposal. It is not 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 that 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 much 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 built-in feature. To make something built-in, one should show that it is so frequently written, and/or that it is difficult to work around. We are not sure that retaining a historical context is a very frequent code pattern (@mrkn said that cumulative sum is actually often used in mathematics, but other use case than cumulative sum was not clear).

Even if it's only cumulative sum, that's still quite useful. And if the cumulative 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 evolution 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 assignment in the block, but the initialization of a variable outside the block.



----------------------------------------
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 results that are computed. As a comparison:
```
[1, 2, 3].inject(0, &:+) => 6
[1, 2, 3].accumulate(0, &:+) => [0, 1, 3, 6]
```

Notably, the `accumulate` operation can be done lazily since it doesn't require 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-education/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00).

## Reasoning
We heavily rely on the accumulate operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-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://github.com/ruby/ruby/pull/3078).

Update: @nobu has provided an alternative implementation [here](https://github.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=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [ruby-core:103615] [Ruby master Feature#17016] Enumerable#accumulate
  2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
                   ` (38 preceding siblings ...)
  2021-04-27  9:05 ` [ruby-core:103614] " duerst
@ 2021-04-27 15:14 ` msiegel
  39 siblings, 0 replies; 41+ messages in thread
From: msiegel @ 2021-04-27 15:14 UTC (permalink / raw)
  To: ruby-core

Issue #17016 has been updated by RubyBugs (A Nonymous).


Thanks everyone continuing to discuss whether to add this method to the Ruby lazy Enumerable!

In case it is helpful, please permit me to clarify that this method (and the functional programming pattern it represents) is of **practical**, rather than theoretical benefit.

This method underlies the system presented in the following conference talk _ETL and Event Sourcing_, which daily rebuilds all system state by re-processing enumerations of the history of data extracted from external systems:
* Part 1: https://www.dropbox.com/s/vibkr2edqmtid9n/047_etl_and_event_sourcing_marc_siegel_panorama_education_part_1.mp4?dl=0
* Part 2: https://www.dropbox.com/s/o6bwxymrkmbepgr/048_etl_and_event_sourcing_marc_siegel_panorama_education_part_2.mp4?dl=0

The implementation of this method we use is published here:
  * Rubygems: https://rubygems.org/gems/scan_left
  * Github: https://github.com/panorama-ed/scan_left/

A blog post discussing presenting the gem and discussing its usage is here: https://medium.com/building-panorama-education/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00

Sincere apologies if this additional context is redundant or unnecessary. My intent in presenting this context, again, is to provide context that this is practical code extracted from a production system, rather than a purely theoretical matter of interest.

Thanks again!

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

* 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 results that are computed. As a comparison:
```
[1, 2, 3].inject(0, &:+) => 6
[1, 2, 3].accumulate(0, &:+) => [0, 1, 3, 6]
```

Notably, the `accumulate` operation can be done lazily since it doesn't require 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-education/scan-left-a-lazy-incremental-alternative-to-inject-f6e946f74c00).

## Reasoning
We heavily rely on the accumulate operation. We use an [event-sourcing](https://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 stream events because they cannot fit in memory). Thus the scan operation is much more applicable than the inject operation.

We suspect that there are many applications that could leverage the scan operation. [This question](https://stackoverflow.com/questions/1475808/cumulative-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://github.com/ruby/ruby/pull/3078).

Update: @nobu has provided an alternative implementation [here](https://github.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/

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2021-04-27 15:14 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-07 17:48 [ruby-core:99078] [Ruby master Feature#17016] Enumerable#scan_left finch.parker
2020-07-08  4:00 ` [ruby-core:99083] " sawadatsuyoshi
2020-07-08 14:51 ` [ruby-core:99089] " finch.parker
2020-07-09 21:33 ` [ruby-core:99102] " eregontp
2020-07-10 20:57 ` [ruby-core:99117] " finch.parker
2020-07-11  5:46 ` [ruby-core:99121] " nobu
2020-07-11 17:47 ` [ruby-core:99129] " eregontp
2020-07-11 17:49 ` [ruby-core:99130] " eregontp
2020-07-12  8:52 ` [ruby-core:99133] " nobu
2020-07-12 11:32 ` [ruby-core:99134] " eregontp
2020-07-12 23:51 ` [ruby-core:99141] " shyouhei
2020-07-14 17:50 ` [ruby-core:99167] " finch.parker
2020-07-14 18:20 ` [ruby-core:99168] " finch.parker
2020-07-15 14:33 ` [ruby-core:99177] " eregontp
2020-07-16  5:17 ` [ruby-core:99189] " mame
2020-07-17 14:29 ` [ruby-core:99203] " finch.parker
2020-07-18  3:23 ` [ruby-core:99212] " nobu
2020-07-20  6:02 ` [ruby-core:99234] " matz
2020-07-22 17:23 ` [ruby-core:99270] " finch.parker
2020-07-22 18:12 ` [ruby-core:99274] " msiegel
2020-07-23  3:12 ` [ruby-core:99286] " nobu
2020-07-23 15:39 ` [ruby-core:99301] " finch.parker
2020-07-23 21:44 ` [ruby-core:99307] " annikoff
2020-07-24  2:30 ` [ruby-core:99310] " nobu
2020-07-25  6:20 ` [ruby-core:99327] " duerst
2020-07-25  7:49 ` [ruby-core:99328] " duerst
2020-07-25 10:12 ` [ruby-core:99330] " annikoff
2020-07-28 17:42 ` [ruby-core:99367] " msiegel
2020-07-28 23:34 ` [ruby-core:99378] " duerst
2020-07-30 19:16 ` [ruby-core:99404] " finch.parker
2020-07-31  5:47 ` [ruby-core:99410] " nobu
2020-08-10 16:47 ` [ruby-core:99545] " finch.parker
2020-08-21 14:22 ` [ruby-core:99664] " finch.parker
2020-08-29 11:41 ` [ruby-core:99769] " daniel
2020-09-03 14:57 ` [ruby-core:99880] " finch.parker
2020-11-10 14:06 ` [ruby-core:100762] " annikoff
2020-11-30 14:38 ` [ruby-core:101156] " finch.parker
2021-04-13 14:51 ` [ruby-core:103429] " finch.parker
2021-04-17  8:15 ` [ruby-core:103497] [Ruby master Feature#17016] Enumerable#accumulate mame
2021-04-27  9:05 ` [ruby-core:103614] " duerst
2021-04-27 15:14 ` [ruby-core:103615] " msiegel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).