【一人 Ruby Advent Calendar 2017】Ruby に Method#=== が入った!!【13日目】

一人 Ruby Advent Calendar 2017 13日目の記事になります。

と、言うことでわたしが提案してパッチを投げていた Method#=== が本体にマッジされました!!やった!!!
これにより以下のように case-whenwhen 節で Method オブジェクトを使えるようになります。

# when で使用する
def check value
    case value
    when 0.method(:<)
        "plus"
    when 0.method(:>)
        "minus"
    when 0.method(:==)
        "zero"
    end
end

p check 3   # => "plus"
p check -6  # => "minus"
p check 0   # => "zero"

やった!!!

経緯

元々以前から『Method#=== がなくてつらいぽよ〜』みたいな事を言っており『Method#=== を定義するだけの gem』なんかもつくっていました。
個人的に『外部で解決が出来るなら』別に本体になくてもいいかなーと思っている派なので特にパッチなどを書くつもりはありませんでした。
でもやっぱり『Proc#=== あるのに Method#=== がないのはおかしいよなー本体でもほしいなー』と思い Ruby 2.5 のドサクサに紛れて入れてしまおうかと急遽パッチを投げることに

Ruby のビルドとパッチの作成

Ruby のビルドやパッチを作ったことがなかったので知人のコミッターに聞いたり以下のサイトを参考にして手元で動作するようにしました。



今回は Method#===Method#call を呼び出すだけだったので実装自体は30秒ぐらいで終わりました。
あとはテストを追加したぐらいですね。
で、作成したパッチは以下のような感じです。

diff --git proc.c proc.c
index cf6e1e85c7..046c0bdf97 100644
--- proc.c
+++ proc.c
@@ -3124,6 +3124,7 @@ Init_Proc(void)
     rb_define_method(rb_cMethod, "hash", method_hash, 0);
     rb_define_method(rb_cMethod, "clone", method_clone, 0);
     rb_define_method(rb_cMethod, "call", rb_method_call, -1);
+    rb_define_method(rb_cMethod, "===", rb_method_call, -1);
     rb_define_method(rb_cMethod, "curry", rb_method_curry, -1);
     rb_define_method(rb_cMethod, "[]", rb_method_call, -1);
     rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
diff --git test/ruby/test_method.rb test/ruby/test_method.rb
index 778fcdc9bc..b3d4098a1c 100644
--- test/ruby/test_method.rb
+++ test/ruby/test_method.rb
@@ -1017,4 +1017,10 @@ def test_argument_error_location
     # without trace insn
     assert_separately [], "RubyVM::InstructionSequence.compile_option = {trace_instruction: false}\n" + body
   end
+
+  def test_eqq
+    assert(Method.instance_methods(false).include? :===)
+    assert_operator(0.method(:<), :===, 5)
+    assert_not_operator(0.method(:<), :===, -5)
+  end
 end

パッチ自体はすごく短いです。
どうでもいいですが、初めて Ruby をビルドしたんですが手元のマシンだと1〜2分で終了したのですごかった…。
Vim をビルドするよりも短い…。

チケットの登録

今回はバグではなくて『新しい機能(メソッド)』の提案だったのでトラッカーは『Feature』を指定。
あとは『概要』だったり『既存の問題点』だったり『ユースケース』だったり『パッチファイル』などをまとめて『日本語』で作成しました。
実際に作成したチケットはこんな感じ。

ちなみに Rubygithub『にも』ソースコードはあるんですが、今回は github に pull request は行わないで直接パッチファイルを添付しました。

チケット登録後…

どちらかといえば難しかったのがチケット登録後。
登録したのは先月の 11/29 なんですが、スパムが速攻で返信した以外は特にレスポンスがなくてどうするべきなのか困っていました。
一応知人がコメントしてくれたんですがそれも特に反応がなく、どうアプローチするべきか全くわからず…。
まあ 2.5 リリース前で忙しいだろうからしゃーないなーと思っていたんですが、今日 Twitter愚痴っていたら Ruby コミッターの方に拾ってもらい無事に取り込んでもらいました(あと知人もプッシュしてくれたみたい?

いやー本当は今日あった DevelopersMeeting にでも乗り込んで直接聞いてみようかと思っていたんですが体調不良により死んでおり…。
なのでもうタイミングがないと思いほとんど諦めていたんですがなんとか Ruby 2.5 に間に合ってよかったよかった…。

そんな感じで Ruby コミッターの方々ありがとうございます。
Rubycase-when 楽しいのでみんなもっと使おう。