Feature #19764
openIntroduce defp keyword for defining overloadable, pattern matched methods
Description
Pattern matching has become one of my favorite features of Ruby, if not my favorite. It changed the way I write and express my thoughts through clean, maintainable code. And I'd like to use it more.
I propose a new keyword, defp
, for defining a method which applies pattern matching to its arguments.
defp call(String => s unless s in /^[a-z]/)
puts "string: #{s.inspect} (capitalized)"
end
defp call(String => s)
puts "string: #{s.inspect}"
end
defp call(Hash(foo:, bar:) => h)
puts "hash: #{h.inspect}"
end
defp call(**nil)
puts "no keyword args"
end
call("Example") # => string: "Example" (capitalized)
call("test") # => string: "test"
call(foo: 1, bar: 2)
# => hash: { :foo => 1, :bar => 2 }
Internally, this could be represented as the following case..in
pseudocode:
def call(...)
case ...
in String => s unless s in /foo/
puts "string: #{s.inspect} (not foo)"
in String => s
puts "string: #{s.inspect}"
in Hash(foo:, bar:) => h
puts "hash: #{h.inspect}"
in **nil
puts "no keyword args"
else
raise NoMatchingMethod
end
end
As you could imagine, this could be used to refactor a lot of code, making the developer's intent much clearer. From complex methods that use case
statements for taking varied arguments (I'm sure all our code bases contain such case
statements), to defining smaller, simpler methods that handle particular argument patterns.
In addition, not only can this improve code quality, but it brings in method overloads, and it also adds a way to define more typing to the language -- something that RBS has tried to do, to mixed reactions -- but in a more Ruby-like way that Rubyists are already learning and loving.
Thoughts?
Original idea by Victor Shepelev: https://zverok.space/blog/2023-05-05-ruby-types.html
Further discussion: https://news.ycombinator.com/item?id=35834351