From: "mame (Yusuke Endoh) via ruby-core" Date: 2024-03-12T03:29:17+00:00 Subject: [ruby-core:117104] [Ruby master Feature#20318] Pattern matching `case ... in` support for triple-dot arguments Issue #20318 has been updated by mame (Yusuke Endoh). I strongly feel "bad smell" for this proposal. In principle, one method should do one thing. But this syntax introduces a completly different branching depending on the arguments, which could encourage a weird method behavior. In fact, the motivating example prints different messages depending on the arguments. I believe such a method would never be recommended. In particular, the method that accepts `foo(str)` and `foo(greeting: str)` but not `foo(str, greeting: str)` looks rather weird to me. I am concerned that such a method could be so easily defined. Considering the Java overloading, each overloaded method definition would often delegate to the most common (receives the most arguments) definition. Given that, the motivating example should be: ```ruby def foo(...) case ... in args: [name] puts "Hello #{ name }" in args: [first_name, last_name] foo(first_name + " " + last_name) in kwargs: {greeting:} foo(greeting) else raise ArgumentError end end ```` I do not find this code easy to understand. As far as I know, Ruby has the most complicated argument system in the world. I don't think we should make it even more complicated. ---------------------------------------- Feature #20318: Pattern matching `case ... in` support for triple-dot arguments https://bugs.ruby-lang.org/issues/20318#change-107177 * 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/