Project

General

Profile

Feature #19764

Updated by zeke (Zeke Gabrielse) 10 months ago

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. 

 ```ruby 
 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: 

 ```ruby 
 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](https://github.com/rails/rails/blob/593893c901f87b4ed205751f72df41519b4d2da3/actionpack/lib/action_dispatch/routing/url_for.rb#L173-L193) 
 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

Back