2019/11/12 Revertされたので使えなくなりました
👋
https://github.com/ruby/ruby/commit/fb6a489af2765a3b56e301adf0019af6bbad6156
https://bugs.ruby-lang.org/issues/16275
以下、deprecated
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種類、記号減ることもある。