Ruby introduces find pattern in pattern matching


As we know that, Ruby 2.7 has introduced pattern matching (Here are the slides to pattern matching for a quick refresher).

Now, Ruby has added support for find pattern in the pattern matching.

Before

If we wanted to pattern match with one of the items in an array, it was not possible before as demonstrated below:

json = {name: "John", friends: [{name: "Alex", age: 24}, {name: "Don", age: 25}]}
case json
in {name: "John", friends: [{name: "Alex", age: age}]}
  p age
end
NoMatchingPatternError ({:name=>"John", :friends=>[{:name=>"Alex", :age=>24}, {:name=>"Don", :age=>25}]})

After

Now we can specify * before and after the item if we want to match an element in an array which contains more than one item as shown below:

json = {name: "John", friends: [{name: "Alex", age: 24}, {name: "Don", age: 25}]}
case json
in {name: "John", friends: [*,{name: "Alex", age: age}, *]}
  p age
end

# => 24

Let’s have a look at some more examples:

case ["a", "b", 23, "c", "d", "e", 48]
in [*pre, String => x, String => y, *post]
  p pre   # => []
  p x     # => "a"
  p y     # => "b"
  p post  # =>  [23, "c", "d", "e", 48]
end

In this example, since the pattern specifies to have two strings consecutively, an empty array is assigned to pre, "a" is assigned to x, "b" is assigned to y. This is because the consecutive strings are present in the starting of the array, which leaves no element to pre. Finally [23, "c", "d", "e", 48] is assigned to post as those are the remaining elements in the array.

case ["alpha", 1, "beta", "gamma", 2, "a", "b", "c", 3]
in [*pre, String => x, String => y, *post]
  p pre   # => ["alpha", 1]
  p x     # => "beta"
  p y     # => "gamma"
  p post  # => [2, "a", "b", "c", 3]
end

In this example, the pattern being matched is the same as above, but input is changed. As you can see in the given input, the first consecutive strings are "beta" and "gamma". Hence all the elements present before the pattern are assigned to pre. "beta" is assigned to x and "gamma" is expected to y as expected. The remaining elements are assigned to post.