Edited at

Ruby 2.7の新機能メソッド参照演算子

methodメソッドを短く書けるメソッド参照演算子の紹介です。

https://bugs.ruby-lang.org/issues/12125

https://github.com/ruby/ruby/commit/67c574736912003c377218153f9d3b9c0c96a17b


methodメソッドとは

メソッドをMethodオブジェクトとして取り出せるべんりメソッド

https://docs.ruby-lang.org/ja/latest/method/Object/i/method.html

123.method(:to_s)

# => #<Method: Integer#to_s>


Methodオブジェクトとは

メソッドとレシーバーが対になったオブジェクトでProcと同じように呼び出せる。

https://docs.ruby-lang.org/ja/latest/class/Method.html

meth = 123.method(:to_s)

# => #<Method: Integer#to_s>
meth.call
# => "123"
meth.call(16)
# => "7b"


メソッド参照演算子

.:methodメソッドと同じようにメソッドをMethodオブジェクトとして取り出せる。

123.:to_s

# => #<Method: Integer#to_s>


methodメソッドが上書きされていても.:ならMethodオブジェクトを取り出せる

methodメソッドが上書きされていてもメソッド参照演算子はメソッドを取り出せる。べんり。

class Object

def method(*)
nil
end
end

123.method(:to_s)
# => nil

123.:to_s.call
# => "123"

Refinementsで上書きされていても大丈夫

using Module.new {

refine(Object) do
def method(*); end
end
}
method(:puts)
# => nil
self.:puts
# => #<Method: main.puts>

methodメソッド同様Refinementsで定義したメソッドは取り出せない

using Module.new {

refine(Object) do
def method(*); end
end
}
self.:method.call(:puts).call(1)
# 1


単項演算子を取り出す場合

methodメソッド同様-@/+@のような形で取り出せる

1.method(:-@).call

# => -1
1.:-@.call
# => -1


べんりなのか

ブロックわたして何かする系のEnumerable的な処理書くときに便利そう。

[1,2,3].map(&2.:*)

# => [2, 4, 6]

["エロ"].any?(&"イエロー".:include?)
# => true

require "prime"
(1..10).select(&Prime.:prime?)
# => [2, 3, 5, 7]


まとめ

trunkのrubyを入れるとすぐに.:を使えるのでべんりです。


2019/03/08 追記

よくある反応についての感想です。


.:違和感ある

他言語ではメソッド呼び出しで()が必要だから()なしで参照が取れたりするけどRubyでは()省略できるのでそれではダメそう。

メソッド呼び出しの.の後ろに:1文字つけくわえるだけ、通常のメソッド呼び出しより1文字多いだけで参照とれるのはそこまで違和感がない気持ち。


記号多い

実際{|x| y.foo(x) }は記号6種類ぐらい使っているので(&y.:foo)は記号5種類、記号減ることもある。