Feature #19840
closed[Proposal] Expand Find pattern to Multiple Find
Description
Hello! I love Ruby's pattern matching features. I would like to propose an expansion of the Find pattern which allows the selection of multiple matching elements of an array.
I often find myself dealing with data like this:
My problem is that I need to retrieve all the id values from the nested array of hashes, and I don't know how many there will be in advance.
It seems that the Find pattern could be expanded from allowing pattern (matching a single element) to *pattern. Examples:
# Base case
case { results: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] }
in results: [*{ id: ids }]
"matched: #{ids}"
else
"not matched"
end
#=> matched: [1, 2]
# With * at the end (rest of args) - same result
case { results: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] }
in results: [*{ id: ids }, *]
"matched: #{ids}"
else
"not matched"
end
#=> matched: [1, 2]
# When one element doesn't match and there is no *rest
case { results: [{ name: "foo" }, { id: 2, name: "bar" }] }
in results: [*{ id: ids }]
"matched: #{ids}"
else
"not matched"
end
#=> not matched
Similarly, *Constant could work to pull out types with an As pattern:
case [1, 2, 3, "string"]
in *Integer => nums, *
"matched: #{nums}"
else
"not matched"
end
#=> matched: [1, 2, 3]
Other patterns would work in the same way. Essentially, this expands the concept of * in pattern matching to mean "a variable number of things matching subpattern". Today, the only pattern supported by * is a variable binding - but it could be any of the other subpatterns as well.
This proposal does imply that this would work:
To me, the * represents the variable number of matches, so the syntax makes intuitive sense. But others may have different opinions about *^ being adjacent.
It may also imply this would work, though we could restrict the number of non-variable patterns (in other words, patterns that have the possibility of not matching) to 1 per Array so that this isn't possible.. I'm not sure something like this would be useful or clear.
This feature feels like the missing piece of the Find pattern to me - I often want to "Find Multiple". If others agree, I would be happy to contribute by working on this feature and creating a pull request.