🦔

[Bug #19990] Could we reconsider the second argument to Kernel#load?

2024/02/12に公開

[Bug #19990] Could we reconsider the second argument to Kernel#load?

  • #load は他のファイルのコードを読み込んできて実行する機能になる
# b.rb
def hoge
  "hoge"
end

class C
end

X = 42
# a.rb
load "./b.rb", false

pp hoge   # => "hjoge"
pp C      # => C
pp X      # => 42
# a.rb
# #load の第二引数に true を渡すと無名モジュールに b.rb のトップレベルが定義される
load "./b.rb", true

pp hoge   # error
pp C      # error
pp X      # error
  • ただし、以下のように :: を付けて定義した場合は無名モジュールではなくてトップレベルのオブジェクトとして定義される
# b.rb
# :: を付けてクラスや定数を定義する
class ::C
end

::X = 42
# a.rb
load "./b.rb", true

pp C   # => C
pp X   # => 42
  • このように #load の第二引数によって制御されたりされなかったりする事があるのでドキュメントを見直したり、機能を見直したり、機能自体を削除したほうがいいんじゃないか、という旨のチケット
    • 元のドキュメントだと protecting the calling program と書かれているが、実際にはそうではない、という点が起点
  • 他にもロードする側で次のようにクラウを再オープンしてメソッドを定義している場合に true を渡した場合とそうでない場合で挙動が変わる
# b.rb
class String
  def foo
  end
end

"hoge".foo
# load "./b.rb"       => OK
# load "./b.rb", true => undefined method `foo' for "hoge":String (NoMethodError)
  • エッジケースではあるけど細かい挙動を付いていくといろいろと問題がありそうだなあ…
    • 個人的には #load(file, true) はつかったことはない
GitHubで編集を提案

Discussion