[#114181] [Ruby master Bug#19767] [Not really a bug, but more a not ideal notification] "historical binary regexp match" when using the "n" modifier in a ruby regex — "rubyFeedback (robert heiler) via ruby-core" <ruby-core@...>
SXNzdWUgIzE5NzY3IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHJ1YnlGZWVkYmFjayAocm9iZXJ0IGhl
3 messages
2023/07/14
[ruby-core:114225] [Ruby master Feature#19764] Introduce defp keyword for defining overloadable, pattern matched methods
From:
"nobu (Nobuyoshi Nakada) via ruby-core" <ruby-core@...>
Date:
2023-07-18 02:57:53 UTC
List:
ruby-core #114225
Issue #19764 has been updated by nobu (Nobuyoshi Nakada).
zeke (Zeke Gabrielse) wrote:
> ```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
> ```
BTW, I found this would be able to extend.
```ruby
def call(...)
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"
end
```
----------------------------------------
Feature #19764: Introduce defp keyword for defining overloadable, pattern matched methods
https://bugs.ruby-lang.org/issues/19764#change-103911
* Author: zeke (Zeke Gabrielse)
* Status: Open
* Priority: Normal
----------------------------------------
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
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/