🤖

【Ruby 4.0 Advent Calender】*nil が nil.to_a を呼び出さなくなる【1日目】

に公開

Ruby 4.0 Advent Calender 1日目の記事です。

これはなに

今年 2025年12月25日にリリースされる予定の Ruby 4.0 の新機能や変更点などを1つずつ紹介していく Advent Calender になります。
基本的には NEWS に載っている機能を紹介すると思うんですがここにない機能についても書くかもしれません。
また、記事を書いてる時点ではまだ Ruby 4.0 はリリースされる前なので Ruby 4.0 がリリースされた時点で機能が変わっている 可能性があるかもしれないので注意してください。
記事のまとめは ここを参照 してください。

*nilnil.to_a を呼び出さなくなる

Ruby では *obj を引数に渡すと内部で obj.to_a が呼び出され、その結果を引数として渡します。

class X
  def to_a
    [1, 2, 3]
  end
end

def check(*args)
  p "args: #{args}"
end

x = X.new

# x.to_a の結果を引数として渡す
check(*x)
# => "args: [1, 2, 3]"

これは *nil のときも同様で nil.to_a の結果を返すようになっていました。

def check(*args)
  pp "args: #{args}"
end

# nil.to_a は [] を返す
p nil.to_a # => []

# nil.to_a の結果を渡す
check(*nil)
# => "args: [1, 2, 3]"

これが Ruby 4.0 では nil.to_a は内部で呼び出さなくなりました。

class NilClass
  # 通常であればこんな定義はしないが…
  def to_a
    [1, 2, 3]
  end
end

def check(*args)
  pp "args: #{args}"
end

# nil.to_a を再定義した値を返す
p nil.to_a # => [1, 2, 3]

# Ruby 3.4 では nil.to_a を渡していたが Ruby 4.0 からは [] で固定される
check(*nil)
# Ruby 3.4 => "args: [1, 2, 3]"
# Ruby 4.0 => "args: []"

モチベーションとしては似たような構文である **nil も内部では #to_h#to_hash は呼び出されないのでそれと一貫するようにしたのと #to_a を呼び出さないようにすることで最適化されることを期待しています。

ユーザ側で nil.to_a に処理をフックしたり、結果を変更している場合には影響がある変更かもしれませんが、そういうことをしてなければ特にユーザ影響はないはずです。

関連

GitHubで編集を提案

Discussion