Ruby 2.7 の変更点 - Module

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

qiita.com

Module

Module#ruby2_keywords 追加

3日目に書いたように、2.7 だとキーワード引数を Hash の形式で渡した場合に warning が出るようになったのですが、次のようなコードがあった場合、

class A
  def hoge(*args)
    args          #=> [{:k=>123}]
    fuga(*args)
  end

  def fuga(*args, **kw)
    args          #=> []
    kw            #=> {:k=>123}
  end
end
A.new.hoge(k: 123)

最初の hoge 呼び出し時はキーワード引数っぽい呼び出しなんだけど、hoge が一旦 *args で受けてからキーワード引数じゃないっぽく fuga に渡してるから、2.7 だと次のような warning が出てしまいます。

test.rb:4: warning: The last argument is used as the keyword parameter
test.rb:7: warning: for `fuga' defined here

メソッドに対して ruby2_keywords と指定することにより、この warning を抑止するということのようです。

class A
  ruby2_keywords def hoge(*args)
    args          #=> [{:k=>123}]
    fuga(*args)
  end

  def fuga(*args, **kw)
    args          #=> []
    kw            #=> {:k=>123}
  end
end
A.new.hoge(k: 123)

なお ruby2_keywords def という妙な構文が入ったわけじゃなくて、メソッド名のシンボルを引数としているだけなので、次のようにも書けます。

  def hoge(*args)
    args
    fuga(*args)
  end
  ruby2_keywords :hoge

うーん、正直キーワード引数まわりはややこしくてよくわからない…。

Module#autoload? : inherit 引数追加

Module#autoload? は定数がオートロードされるものであれば、そのオートロードファイル名を返すものらしいです(初めて知った)。

class A
  autoload :HOGE, "hoge.rb"
end
class B < A
end
A.autoload?(:HOGE)  #=> "hoge.rb"
B.autoload?(:HOGE)  #=> "hoge.rb"

継承された時にそれを返すかどうかを引数で指定できるようになりました。

class A
  autoload :HOGE, "hoge.rb"
end
class B < A
end
p A.autoload?(:HOGE)        #=> "hoge.rb"
p A.autoload?(:HOGE, false) #=> "hoge.rb"
p B.autoload?(:HOGE)        #=> "hoge.rb"
p B.autoload?(:HOGE, false) #=> nil

Module#const_source_location 追加

定数の定義位置を返します。

module Hoge
  C = 123
end
Hoge.const_source_location(:C)       #=> ["test.rb", 2]
Object.const_source_location(:Hoge)  #=> ["test.rb", 1]

Module#name が同じオブジェクトを返す

Module#name が返す文字列が同じオブジェクトになります。(ただし experimental)

module Hoge
end

Hoge.name.object_id == Hoge.name.object_id  #=> true (2.6 では false)