Skip to content

Instantly share code, notes, and snippets.

@wanabe
Last active March 23, 2025 09:11
Show Gist options
  • Save wanabe/5b17646c781eafb42d341d4f83107acc to your computer and use it in GitHub Desktop.
Save wanabe/5b17646c781eafb42d341d4f83107acc to your computer and use it in GitHub Desktop.

Method クラスとは

メソッドとレシーバの組み合わせのオブジェクト。Method.new ではなく Object#method で作成する。 Methd#call メソッドで呼び出しできる。ruby-1.1b9_01 と初期からある。

$ docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p Method'

...
ruby-1.1b9            -e:1: Uninitialized constant Method (NameError)
                  exit 1
ruby-1.1b9_01         Method
...
ruby-3.4.1            Method
$ docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p "a".method(:to_s)'
...
ruby-1.1b9            -e:1: undefined method `method' for "a" (NameError)
                  exit 1
ruby-1.1b9_01         #<Method: String#to_s>
...
ruby-1.4.6            #<Method: String#to_s>
ruby-1.6.0            #<Method: String(String)#to_s>
...
ruby-1.6.8            #<Method: String(String)#to_s>
ruby-1.8.0            #<Method: String#to_s>
...
ruby-2.7.0-preview2   #<Method: String#to_s>
ruby-2.7.0-preview3   #<Method: String#to_s()>
...
ruby-3.4.1            #<Method: String#to_s()>

UnboundMethod クラスとは

メソッドオブジェクト。UnboundMethod.new ではなく Module#instance_method などで作成する。 UnboundMethd#bindMethod を作成しないと呼び出しできない。ruby-1.6.0 からある。

$ docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p UnboundMethod'
...
ruby-1.4.6            /tmp/rb8oZM7a:1: uninitialized constant UnboundMethod (NameError)
                  exit 1
ruby-1.6.0            UnboundMethod
...
ruby-3.4.1            UnboundMethod
$ docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p String.instance_method(:to_s)'
...
ruby-1.4.6            /tmp/rbfTqSUb:1: undefined method `instance_method' for String:Class (NameError)
                  exit 1
ruby-1.6.0            #<UnboundMethod: String(String)#to_s>
...
ruby-1.6.8            #<UnboundMethod: String(String)#to_s>
ruby-1.8.0            #<UnboundMethod: String#to_s>
...
ruby-2.7.0-preview2   #<UnboundMethod: String#to_s>
ruby-2.7.0-preview3   #<UnboundMethod: String#to_s()>
...
ruby-3.4.1            #<UnboundMethod: String#to_s()>

struct METHOD とは

Method および nboundMethod の中身の C 構造体。変遷を確認するためスクリプトを用意した。

require "time"
commit = "HEAD"
loop do
  $stderr.puts
  commit=`git log -n1 --format=%h  #{commit}~`.chomp
  file = `git grep --name-only "^struct METHOD {" #{commit}`[/^[0-9a-f]*:(.*)/, 1]
  break unless file
  struct_def = `git blame --no-progress #{commit} #{file}`.gsub(/\r\n/, "\n")[/.*\) struct METHOD {(?:\n.*)*?\n.*\) \};$/]

  t = Time.at(0)
  struct_def.each_line do |l|
    l =~ /^([0-9a-f]+) \(.* ([-0-9]+ [:0-9]+ [+0-9]+) +[0-9]+\) (.*)/
    hash, timestr, line = $1, $2, $3
    time = Time.parse(timestr)
    if time > t
      t = time
      commit = hash
    end
  end
  tag = `git tag --contains  #{commit}`.lines.grep(/^v/).min.chomp
  puts "#{commit}(#{tag}):#{file}", struct_def

  if system("git notes --ref ruby-trunk-changes show #{commit} >/dev/null") 
    rev = `git log -n1 #{commit}`[/ *git-svn-id:.*@([0-9]*)/, 1]
    search = rev ? "r#{rev}" : commit
    puts "https://ruby-trunk-changes.hatenablog.com/search?q=#{search}"
  end
end

実行結果は以下の通り。

$ ruby history.rb 

6b7d32a5e54(v3_2_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   29) struct METHOD {
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   30)     const VALUE recv;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   31)     const VALUE klass;
6b7d32a5e54 (Benoit Daloze             2022-09-28 19:49:13 +0200   32)     /* needed for #super_method */
a15028bc38a (Nobuyoshi Nakada          2017-10-06 05:55:11 +0000   33)     const VALUE iclass;
6b7d32a5e54 (Benoit Daloze             2022-09-28 19:49:13 +0200   34)     /* Different than me->owner only for ZSUPER methods.
6b7d32a5e54 (Benoit Daloze             2022-09-28 19:49:13 +0200   35)        This is error-prone but unavoidable unless ZSUPER methods are removed. */
6b7d32a5e54 (Benoit Daloze             2022-09-28 19:49:13 +0200   36)     const VALUE owner;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   37)     const rb_method_entry_t * const me;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   38)     /* for bound methods, `me' should be rb_callable_method_entry_t * */
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   39) };
https://ruby-trunk-changes.hatenablog.com/search?q=6b7d32a5e54

a15028bc38a(v2_5_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   37) struct METHOD {
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   38)     const VALUE recv;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   39)     const VALUE klass;
a15028bc38a (Nobuyoshi Nakada          2017-10-06 05:55:11 +0000   40)     const VALUE iclass;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   41)     const rb_method_entry_t * const me;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   42)     /* for bound methods, `me' should be rb_callable_method_entry_t * */
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   43) };
https://ruby-trunk-changes.hatenablog.com/search?q=r60127

5e8a147480f(v2_3_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   29) struct METHOD {
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   30)     const VALUE recv;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   31)     const VALUE klass;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   32)     const rb_method_entry_t * const me;
5e8a147480f (Koichi Sasada             2015-07-03 11:24:50 +0000   33)     /* for bound methods, `me' should be rb_callable_method_entry_t * */
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   34) };
https://ruby-trunk-changes.hatenablog.com/search?q=r51126

57b817f4c55(v2_3_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   23) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   24)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   25)     VALUE rclass;
319088e9c7a (Shugo Maeda               2012-08-02 11:08:44 +0000   26)     VALUE defined_class;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   27)     ID id;
57b817f4c55 (Koichi Sasada             2015-06-02 04:20:30 +0000   28)     rb_method_entry_t * const me;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   29) };
https://ruby-trunk-changes.hatenablog.com/search?q=r50728

319088e9c7a(v2_0_0_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   19) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   20)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   21)     VALUE rclass;
319088e9c7a (Shugo Maeda               2012-08-02 11:08:44 +0000   22)     VALUE defined_class;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   23)     ID id;
9a27239558d (Yusuke Endoh              2011-07-25 14:29:28 +0000   24)     rb_method_entry_t *me;
da5b7f9229f (Yusuke Endoh              2011-07-25 15:17:56 +0000   25)     struct unlinked_method_entry_list_entry *ume;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   26) };
https://ruby-trunk-changes.hatenablog.com/search?q=r36595

da5b7f9229f(v2_0_0_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   17) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   18)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   19)     VALUE rclass;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   20)     ID id;
9a27239558d (Yusuke Endoh              2011-07-25 14:29:28 +0000   21)     rb_method_entry_t *me;
da5b7f9229f (Yusuke Endoh              2011-07-25 15:17:56 +0000   22)     struct unlinked_method_entry_list_entry *ume;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   23) };
https://ruby-trunk-changes.hatenablog.com/search?q=r32671

9a27239558d(v2_0_0_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   17) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   18)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   19)     VALUE rclass;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   20)     ID id;
9a27239558d (Yusuke Endoh              2011-07-25 14:29:28 +0000   21)     rb_method_entry_t *me;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   22) };
https://ruby-trunk-changes.hatenablog.com/search?q=r32669

fcf88c1b8df(v1_9_2_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   17) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   18)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   19)     VALUE rclass;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   20)     ID id;
fcf88c1b8df (Nobuyoshi Nakada          2009-08-28 02:45:41 +0000   21)     rb_method_entry_t me;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   22) };
error: no note found for object fcf88c1b8df49ba0c4db026f2b17066ea66d3de2.

c330876d7c5(v1_9_2_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   15) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   16)     VALUE recv;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   17)     VALUE rclass;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   18)     ID id;
c330876d7c5 (Koichi Sasada             2009-07-15 14:59:41 +0000   19)     rb_method_entry_t *me;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   20) };
error: no note found for object c330876d7c5065f89234becc5125426d0d136bdc.

87ea50380d0(v1_9_0_1):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   15) struct METHOD {
c227d3feb39 (Yukihiro "Matz" Matsumoto 2007-11-22 01:17:52 +0000   16)     VALUE oclass;                /* class that holds the method */
87ea50380d0 (Tanaka Akira              2008-02-09 09:49:31 +0000   17)     VALUE rclass;                /* class of the receiver */
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   18)     VALUE recv;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   19)     ID id, oid;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   20)     NODE *body;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   21) };
error: no note found for object 87ea50380d06e71889251a22e86731c7f1dfa6bb.

c227d3feb39(v1_9_0_0):proc.c
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   15) struct METHOD {
c227d3feb39 (Yukihiro "Matz" Matsumoto 2007-11-22 01:17:52 +0000   16)     VALUE oclass;                /* class that holds the method */
c227d3feb39 (Yukihiro "Matz" Matsumoto 2007-11-22 01:17:52 +0000   17)     VALUE rclass;                /* class of the recevier */
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   18)     VALUE recv;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   19)     ID id, oid;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   20)     NODE *body;
c1f5d227197 (Nobuyoshi Nakada          2007-02-02 15:21:41 +0000   21) };
error: no note found for object c227d3feb393c7aaa4e40612dc1ac39e598df3b4.

c1f5d227197(v1_9_0_0):proc.c
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   16) struct METHOD {
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   17)     VALUE klass, rklass;
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   18)     VALUE recv;
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   19)     ID id, oid;
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   20)     NODE *body;
c1f5d227197 (Nobuyoshi Nakada 2007-02-02 15:21:41 +0000   21) };
error: no note found for object c1f5d2271974b3b36a472a3af3c2acd275c69a65.

dbee6786307(v1_9_0_0):proc.c
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   16) struct METHOD {
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   17)     VALUE klass, rklass;
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   18)     VALUE recv;
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   19)     ID id, oid;
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   20)     NODE *body;
dbee6786307 (Koichi Sasada             2007-01-17 08:48:52 +0000   21) };
error: no note found for object dbee678630736a5d873cde1f262bf2cfc87e8dfe.

a3e1b1ce7ed(v1_9_0_0):eval_proc.c
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000    7) struct METHOD {
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000    8)     VALUE klass, rklass;
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000    9)     VALUE recv;
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000   10)     ID id, oid;
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000   11)     NODE *body;
a3e1b1ce7ed (Koichi Sasada 2006-12-31 15:02:22 +0000   12) };
error: no note found for object a3e1b1ce7ed7e7ffac23015fc2fde56511b30681.

5b014a7427e(v1_9_0_0):env.h
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 59) struct METHOD {
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 60)     VALUE klass, rklass;
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 61)     VALUE recv;
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 62)     ID id, oid;
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 63)     int safe_level;
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 64)     struct RNode *body;
5b014a7427e (Yukihiro "Matz" Matsumoto 2005-10-21 09:00:02 +0000 65) };
error: no note found for object 5b014a7427ef87fecb54c368cf3fe1efabb03f03.

17957e0dfca(v1_9_0_0):eval.c
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8548) struct METHOD {
a7a7324ea64 (Yukihiro "Matz" Matsumoto 2002-01-18 14:24:01 +0000  8549)     VALUE klass, rklass;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8550)     VALUE recv;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8551)     ID id, oid;
17957e0dfca (Yukihiro "Matz" Matsumoto 2005-08-16 15:24:15 +0000  8552)     int safe_level;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8553)     NODE *body;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8554) };
error: no note found for object 17957e0dfca25957556bdccd3590be9b9dee5923.

a7a7324ea64(v1_1_8):eval.c
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8913) struct METHOD {
a7a7324ea64 (Yukihiro "Matz" Matsumoto 2002-01-18 14:24:01 +0000  8914)     VALUE klass, rklass;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8915)     VALUE recv;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8916)     ID id, oid;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8917)     NODE *body;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000  8918) };
error: no note found for object a7a7324ea645b881658fb78d2e7e049f48970afd.

210367ec889(v1_1_8):eval.c
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6674) struct METHOD {
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6675)     VALUE klass, oklass;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6676)     VALUE recv;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6677)     ID id, oid;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6678)     NODE *body;
210367ec889 (Yukihiro "Matz" Matsumoto 1999-01-20 04:59:39 +0000 6679) };
error: no note found for object 210367ec889f5910e270d6ea2c7ddb8a8d939e61.

ruby-trunk-changes の関連するページを正規のリンクに直して箇条書きした。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment