👌
【bugs.ruby Advent Calender】case ~ in ~ end で ... を渡せるようにする提案【4日目】
bugs.ruby Advent Calender 4日目の記事です。
これはなに
今年1年間通してみてきた bugs.ruby のチケットの中から気になったものを1つずつ取り上げていく Advent Calender です。
取り上げるチケットは基本的にこのブログで取り上げたものになります。
記事のまとめは ここを参照 してください。
[Feature #20318] Pattern matching case ... in
support for triple-dot arguments
case ~ in ~ end
で ...
を渡せるようにする提案です。
...
は転送引数で『なんでも受け入れる引数』みたいな構文ですね。
def hoge(...)
# このメソッドに渡された引数をすべて他の引数に転送できる
pp(...)
end
hoge(1, 2, a: 3)
__END__
output:
1
2
{:a=>3}
これとパターンマッチを組み合わせることによって『引数の状態によって処理を切り分ける』ような使い方を想定しています。
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" # => Hi
foo "Brad", "Gessler" # => Hi there Brad Gessler
foo greeting: "Brad" # => Hello Brad
提案では args
が位置引数を参照し kwargs
がキーワード引数を参照する、みたいなイメージですね。
既存のコードでは以下と同じような形になります。
def foo(*args, **kwargs, &block)
case { args:, kwargs:, block: }
in args: [name]
# ...
end
end
他にもコメントで、以下のように case
を省略した書き方があったり
def foo(...)
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
また、既存の 1行メソッド定義で以下のようにかけたりなどいろいろな書き方がでてきていて面白いですねー。
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
foo "Hi" # => Hi
foo "Brad", "Gessler" # => Hi there Brad Gessler
foo greeting: "Brad" # => Hello Brad
いずれの書き方も面白いとは思いつつ、現状の構文と比べてできないことができるようになるわけではないのでなんかもっといい感じの拡張機能がほしいですね。
Discussion