Ruby 3.2 - キーワードパラメータその1、その2

Ruby 3.2 アドベントカレンダーの1日目の記事です。

qiita.com

Ruby は毎年クリスマスにバージョンが上がります。 今年も順調にいけば 12/25 に Ruby 3.2 がリリースされるはずです。 3.2 がリリースされるまで毎日少しずつ変更点を見ていきながらリリースを待ちましょう。

ネタ元は Ruby 3.2 preview3 の NEWS.md


キーワードパラメータその1

Feature #18351: Support anonymous rest and keyword rest argument forwarding - Ruby master - Ruby Issue Tracking System

*** で受け取ったパラメータを引数として使う場合に変数名をつける必要がなくなった。

def hoge(a, *, **)
  a  #=> 123
  fuga(*, **)
end

def fuga(*args, **opts)
  pp args, opts
  #=> [456]
  #   {:x=>"abc", :y=>"def"}
end

hoge(123, 456, x: 'abc', y: 'def')

でもこれキーワードパラメータがあるとエラーになってしまう。

def hoge(a, *, x: nil, **)
  fuga(*, **)   #=> no anonymous keyword rest parameter
end

これはどうやらバグだったらしい。3.2 リリースまでには直りそう。 Bug #19132: ** を引数に指定すると no anonymous keyword rest parameter になる - Ruby master - Ruby Issue Tracking System

キーワードパラメータその2

Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially - Ruby master - Ruby Issue Tracking System

ブロックパラメータがキーワードパラメータを含む場合に、配列を渡した場合の扱いが変わった。 3.1 までは配列の中の要素が展開されてパラメータに格納されたが、3.2 では配列のまま。

Ruby 3.1:

proc{|a| p a}.call([1, 2])         #=> [1, 2]
proc{|a,| p a}.call([1, 2])        #=> 1
proc{|a, k:nil| p a}.call([1, 2])  #=> 1
proc{|a, **k| p a}.call([1, 2])    #=> 1

Ruby 3.2:

proc{|a| p a}.call([1, 2])         #=> [1, 2]
proc{|a,| p a}.call([1, 2])        #=> 1
proc{|a, k:nil| p a}.call([1, 2])  #=> [1, 2]
proc{|a, **k| p a}.call([1, 2])    #=> [1, 2]