[#99002] [Ruby master Feature#17004] Provide a way for methods to omit their return value — shyouhei@...

Issue #17004 has been reported by shyouhei (Shyouhei Urabe).

21 messages 2020/07/01

[#99044] [Ruby master Bug#17007] SystemStackError when using super inside Module included and lexically inside refinement — eregontp@...

Issue #17007 has been reported by Eregon (Benoit Daloze).

7 messages 2020/07/03

[#99078] [Ruby master Feature#17016] Enumerable#scan_left — finch.parker@...

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

42 messages 2020/07/07

[#99079] [Ruby master Bug#17017] Range#max & Range#minmax incorrectly use Float end as max — bosticko@...

Issue #17017 has been reported by sambostock (Sam Bostock).

25 messages 2020/07/07

[#99097] [Ruby master Bug#17021] "arm64" and "arm" are mixed in RbConfig on Apple silicon — watson1978@...

Issue #17021 has been reported by watson1978 (Shizuo Fujita).

9 messages 2020/07/09

[#99115] [Ruby master Bug#17023] How to prevent String memory to be relocated in ruby-ffi — larskanis@...

Issue #17023 has been reported by larskanis (Lars Kanis).

22 messages 2020/07/10

[#99156] [Ruby master Bug#17030] Enumerable#grep{_v} should be optimized for Regexp — marcandre-ruby-core@...

Issue #17030 has been reported by marcandre (Marc-Andre Lafortune).

25 messages 2020/07/13

[#99257] [Ruby master Misc#17041] DevelopersMeeting20200826Japan — mame@...

Issue #17041 has been reported by mame (Yusuke Endoh).

18 messages 2020/07/22

[#99308] [Ruby master Feature#17047] Support parameters for MAIL FROM and RCPT TO — bugs.ruby-lang.org@...

Issue #17047 has been reported by c960657 (Christian Schmidt).

11 messages 2020/07/23

[#99311] [Ruby master Bug#17048] Calling initialize_copy on live modules leads to crashes — XrXr@...

Issue #17048 has been reported by alanwu (Alan Wu).

17 messages 2020/07/24

[#99351] [Ruby master Bug#17052] Ruby with LTO enabled on {aarch64, ppc64le} architectures. — v.ondruch@...

Issue #17052 has been reported by vo.x (Vit Ondruch).

35 messages 2020/07/27

[#99375] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings — merch-redmine@...

Issue #17055 has been reported by jeremyevans0 (Jeremy Evans).

29 messages 2020/07/28

[#99391] [Ruby master Feature#17059] epoll as IO.select — dsh0416@...

Issue #17059 has been reported by dsh0416 (Delton Ding).

18 messages 2020/07/29

[#99418] [Ruby master Feature#17097] `map_min`, `map_max` — sawadatsuyoshi@...

Issue #17097 has been reported by sawa (Tsuyoshi Sawada).

11 messages 2020/07/31

[ruby-core:99117] [Ruby master Feature#17016] Enumerable#scan_left

From: finch.parker@...
Date: 2020-07-10 20:57:30 UTC
List: ruby-core #99117
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/

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

In This Thread