[ruby-core:117119] [Ruby master Feature#20318] Pattern matching `case ... in` support for triple-dot arguments
From:
"matheusrich (Matheus Richard) via ruby-core" <ruby-core@...>
Date:
2024-03-12 17:34:31 UTC
List:
ruby-core #117119
Issue #20318 has been updated by matheusrich (Matheus Richard).
@mame I understand the example is contrived, but even the core library does different things with different arguments. Let's take [`Random.rand`](https://docs.ruby-lang.org/en/3.3/Random.html#method-c-rand) as an example:
```rb
Random.rand(10) # returns an Integer up to 10
Random.rand(10.0) # returns a Float up to 10
Random.rand(0..10) # returns an Integer between 0 and 10
Random.rand(0..10.0) # returns a Float between 0 and 10
``
`
The logic to do this is [spread out in the method definition with several if/else](https://github.com/ruby/ruby/blob/v3_3_0/random.c#L1549). This proposal could streamline those types of interfaces. Granted, this can currently be achieved with the approach @zverok mentioned.
----------------------------------------
Feature #20318: Pattern matching `case ... in` support for triple-dot arguments
https://bugs.ruby-lang.org/issues/20318#change-107195
* Author: bradgessler (Brad Gessler)
* Status: Open
----------------------------------------
# Premise
Sometimes when I'm creating a method for an API, I'd like to do pattern matching against the arguments. Today I have to do something like this:
```ruby
def foo(*args, **kwargs, &block)
case { args:, kwargs:, block: }
in args: [name]
puts name
in args: [first_name, last_name]
puts "Hi there #{first_name} #{last_name}"
in kwargs: {greeting:}
puts "Hello #{greeting}"
else
puts "No match: #{args}"
end
end
foo "Hi"
foo "Brad", "Gessler"
foo greeting: "Brad"
```
Or an array like this:
```ruby
def bar(*args, **kwargs, &block)
case [args, kwargs, block]
in [name], {}, nil
puts name
in [first_name, last_name], {}, nil
puts "Hi there #{first_name} #{last_name}"
in [], {greeting:}, nil
puts "Hello #{greeting}"
else
puts "No match: #{args}, #{kwargs}"
end
end
bar "Howdy"
bar "Bradley", "Gessler"
bar greeting: "Bradley"
```
# Proposal
I'd like to propose the same thing, but for `...`, like this:
```ruby
def foo(...)
case ...
in args: [name]
puts name
in args: [first_name, last_name]
puts "Hi there #{first_name} #{last_name}"
in kwargs: {greeting:}
puts "Hello #{greeting}"
else
puts "No match: #{args}"
end
end
foo "Hi"
foo "Brad", "Gessler"
foo greeting: "Brad"
```
One thing I'm not sure sure about: the `args`, `kwargs`, and `block` names appear out of thin air, so ideally those could somehow be named or have a syntax that doesn't require those names.
The array would look like this:
```ruby
def bar(...)
case ...
in [name], {}, nil
puts name
in [first_name, last_name], {}, nil
puts "Hi there #{first_name} #{last_name}"
in [], {greeting:}, nil
puts "Hello #{greeting}"
else
puts "No match: #{args}, #{kwargs}"
end
end
bar "Howdy"
bar "Bradley", "Gessler"
bar greeting: "Bradley"
```
--
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/