🙆♀️
【Ruby 3.4 Advent Calender】`**nil` が `**{}` と同等に扱われるようになる【2日目】
Ruby 3.4 Advent Calender 2日目の記事です。
これはなに
今年 2024年12月25日にリリースされる予定の Ruby 3.4 の新機能や変更点などを1つずつ紹介していく Advent Calender になります。
基本的には NEWS に載っている機能を紹介すると思うんですがここにない機能についても書くかもしれません。
また、記事を書いてる時点ではまだ Ruby 3.4 はリリースされる前なので Ruby 3.4 がリリースされた時点で機能が変わっている 可能性があるかもしれないので注意してください。
記事のまとめは ここを参照 してください。
**nil
がサポートされた
**
は『 Hash
オブジェクトをキーワード引数として渡す』ような用途で利用します。
User = Data.define(:name, :age)
def create_user(name:, age:)
User.new(name:, age:)
end
users = [
{ name: "homu", age: 14 },
{ name: "mami", age: 15 }
]
data = { name: "homu", age: 14 }
# create_user(name: "homu", age: 14) と同等の呼び出しになる
pp create_user(**data)
# => #<data User name="homu", age=14>
これが Ruby 3.4 からは **nil
が **{}
と同等に扱われるようになります。
def any_method(default: nil)
{ default: }
end
pp any_method(**{ default: false }) # => {:default=>false}
# キーワード引数は何も渡されない
pp any_method(**{}) # => {:default=>nil}
pp any_method(**nil) # => {:default=>nil}
これにより例えば次のようなコードが簡潔にかけるようになります。
User.create(
name: "homu",
age: 14,
# params に :user_options がない場合でも動作するようになる
# 今までは **(params[:user_options] || {}) みたいに書く必要があた
**params[:user_options]
)
**nil
を許容する提案は割と前から話が上がっていたので Ruby 3.4 でサポートされたのは個人的にも嬉しい。
NilClass#to_hash
は依然として未定義
余談: **obj
に関連する話として #to_hash
メソッドがあります。
**obj
では内部で #to_hash
メソッドを呼び、その戻り値の Hash に対して **
を処理します。
class X
def to_hash
{ x: "test" }
end
end
# 内部で X#to_hash が呼び出されて変換される
pp **X.new
# => {:x=>"test"}
なので Ruby 3.4 以前でも NilClass#to_hash
が定義されていれば **nil
が使用できます。
pp RUBY_VERSION # => "3.3.6"
class NilClass
def to_hash = {}
end
# **nil は **{} と同等になる
pp(a: 42, **nil)
# => {:a=>42}
ただし、今回の Ruby 3.4 の **nil
のサポートは NilClass#to_hash
メソッドが追加されたわけではないので注意する必要があります。
pp RUBY_VERSION # => "3.4.0"
# 3.4 でも NilClass#to_hash が使えるようになったわけではない
# error: undefined method 'to_hash' for nil (NoMethodError)
nil.to_hash
Discussion