🐥
[bugs.ruby][Feature #20318] パターンマッチに転送引数を渡せるようにする提案
[Feature #20318] Pattern matching case ... in
support for triple-dot arguments
-
case ... in
で...
を渡せるようにする提案-
...
は転送引数
-
- 現状だと以下のように引数を Hash パターンで書いたり
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"
- Array パターンで書いたりする
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"
- これを以下のように転送引数を直接
case
に渡せるようにする提案
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"
- もしくは
[], {}, block
で受け取るパターン
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"
- また以下のように
def ~ end
構文に直接in
を書く提案もコメントでされている
def foo(...)
in [name] # foo('ko1')
puts name
in [first_name, last_name] # foo('ko1', 'ssd')
puts "Hi there #{first_name} #{last_name}"
in {greeting:} # foo(greeting: 'hello')
puts "Hello #{greeting}"
else
puts "No match: #{args}"
end
- 上記の書き方は以下のように 1行def で似たような書き方ができるともコメントされていますね
- これはこれで面白い
def foo(*, **) = case [*, **]
in name, {}
puts name
in first_name, last_name, {}
puts "Hi there #{first_name} #{last_name}"
in [{greeting:}]
puts "Hello #{greeting}"
in *args
puts "No match: #{args}"
end
foo('ko1') #=> "ko1"
foo('ko1', 'ssd') #=> "Hi there ko1 ssd"
foo(greeting: 'hello') #=> Hello hello
foo('ko1', 'ssd', greeting: 'hello') #=> No match: ["ko1", "ssd", {:greeting=>"hello"}]
- 他にも以下のように
when
で分岐できたり
def foo
when (name) # foo('ko1')
puts name
when (first_name, last_name) # foo('ko1', 'ssd')
puts "Hi there #{first_name} #{last_name}"
when (greeting:) # foo(greeting: 'hello')
puts "Hello #{greeting}"
else
puts "No match: #{args}"
end
- ブロック引数でも利用したいなどのコメントもされています
HTTP.post("http://example.com/some-resource", "some data") do |...|
in code: (200...300)
puts "Success!"
in code: (300...400), location:
puts "Redirect to #{location}"
# post to location
in code: (500...600)
puts "Server error"
do_retry
end
- いずれの書き方も面白いとは思いつつ、現状の構文と比べてできないことができるようになるわけではないのでなんかもっといい感じの拡張機能がほしい
Discussion