Techioz Blog

二重コロンをメソッド呼び出しに使用する場合、二重コロンは内部でどのように機能するのでしょうか?

概要

これは理論的な質問です。 :: を使用してメソッドを呼び出すことができることはわかっています。めったに使用されませんが、使用される可能性があります。例えば:

user = User.new
user::name

問題は、内部でどのように動作しているのかということです。 user::name を実行できる実装の詳細は何ですか?

このメソッドの呼び出し方法が次のように言及されている場所をいくつか見つけました。

しかし、実装の詳細は提供されていません。これは私にとって興味深いトピックです。 Ruby のソースコードも調べてみましたが、今のところは成功しませんでした。

これらのスレッドもチェックしました:

彼らは :: がどのように機能するか、および :: と .. の違いについて説明しています。そして、これは私が探しているものではありません。

:: について詳しく知り、深く理解するのに役立つ情報があれば幸いです。私の質問は、:: の使用方法ではなく、内部でどのように動作するかについてです。 :: の実装の詳細を知りたいです。

解決策

それを知るための 1 つの方法:

puts RubyVM::InstructionSequence.compile("M::M").disasm
puts

puts RubyVM::InstructionSequence.compile("M.m").disasm
puts
puts RubyVM::InstructionSequence.compile("M::m").disasm
# this one does a constant lookup only

== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,4)> (catch: false)
0000 opt_getconstant_path                   <ic:0 M::M>               (   1)[Li]
0002 leave


# these two are identical and do a method call

== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,3)> (catch: false)
0000 opt_getconstant_path                   <ic:0 M>                  (   1)[Li]
0002 opt_send_without_block                 <calldata!mid:m, argc:0, ARGS_SIMPLE>
0004 leave

== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,4)> (catch: false)
0000 opt_getconstant_path                   <ic:0 M>                  (   1)[Li]
0002 opt_send_without_block                 <calldata!mid:m, argc:0, ARGS_SIMPLE>
0004 leave

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://rubyapi.org/3.2/o/rubyvm/instructionsequence

opt_getconstant_path を検索して、:: がコンパイルされる場所を見つけることができます。

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://github.com/ruby/ruby/blob/v3_2_2/compile.c#L9112

c の知識がゼロの私の場合、 ^ は if 何かが定数であること、else 関数が呼び出されることを明確に示しています (コメントにそう書いてあるので :)。