Project

General

Profile

Actions

Feature #17165

open

Add `filter` and `flatten` keywords to `Enumerable#map`

Added by sawa (Tsuyoshi Sawada) about 1 year ago. Updated about 1 year ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:99994]

Description

I had a use case to do map on an enumerable, with 1-level flattening, while skipping nil values.

There are convenient Enumerable#flat_map and Enumerable#filter_map methods, but the problem is that they cannot be used at the same time. I had to chose to do either of the following:

array
.filter_map do |foo|
  bar = baz(foo)
  next unless bar
  bar.map{...}
end
.flatten(1)
array
.flat_map do |foo|
  bar = baz(foo)
  next unless bar
  bar.map{...}
end
.compact
array
.flat_map do |foo|
  bar = baz(foo)
  next [] unless bar
  bar.map{...}
end

The last one of the above may not look so bad, but it requires an extra consideration, and is a bit hacky. When you are in a hurry, it just might not come to your mind.

This led me to realize that flat_map and filter_map should not be independent operations, but are rather some different modes of the operation map. There is no reason for the modes to be mutually exclusive of one another, and a use case that I mentioned above may arise.

I propose to add filter and flatten as optional keyword arguments to Enumerable#map.

array
.map(filter: true, flatten: 1) do |foo|
  bar = baz(foo)
  next unless bar
  bar.map{...}
end

In fact, even when the two parameters are not used together, I believe it would be easier to the brain and I would feel much more comfortable to pass filter: true or flatten: 1 to map when necessary rather than having to deicide whether to use map or flat_map or use map or filter_map.

Furthermore, this would make it possible to do flattening of an arbitrary depth (as specified by the parameter) during map.

Actions

Also available in: Atom PDF