5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ruby | 【衝撃】["d", "i", "c"].map(&:upcase) 一体この&:メソッドってナニナノ?【真相究明】

Last updated at Posted at 2020-03-08

&:メソッドはなんかrubyのそういう省略した書き方ができるイディオムくらいの理解にとどまっていないかい🍓👮👊💘

["d", "i", "c"].map(&:upcase)

=> ["D", "I", "C"]

僕は、「&:」 と 「メソッド名」 でなんかそういう役割をしているものだと思っていまいた :cry:
ただしくは 「&」 と 「メソッド名(シンボル)」なんですね先生🏫 :fu: 🙇♂️ :fu: ‍🏫 👨‍

  • ぼきは DICの卒業生でつ

まず、Symbol#to_procを理解する

まず、リファレンス通り

:to_i.to_proc["ff", 16]  # => 255 ← "ff".to_i(16)と同じ

self に対応する Proc オブジェクトを返します。

生成される Proc オブジェクトを呼びだす(Proc#call)と、 Proc#callの第一引数をレシーバとして、 self という名前のメソッドを残りの引数を渡して呼びだします。

(っ◔◡◔)っ ♥ ちょっと日本語がむつかしい ♥

==> 解剖してみりゅ(☢🐒 お願いし松 🐤✎)

「self に対応する Proc オブジェクトを返します。」💢

シンボルに対してto_procを呼ぶとこういうProcオブジェクトが返るということ
(Symbol#to_procのSymbolは :メソッド を想定しています)

Proc.new{|obj, *args|, obj.send(self, *args)}

:to_iというselfに対応するProcオブジェクトとはこういうこと

:to_i.to_proc

==> Proc.new{|obj, *args| obj.send(:to_i, *args)}

「 Proc#callの第一引数をレシーバとして、 self という名前のメソッドを残りの引数を渡して呼びだします。」💢

proc = :to_i.to_proc
# Proc.new{|obj, *args| obj.send(:to_i, *args)}

proc.call("A", 16) # => 10

# 第一引数("A")をレシーバとして
#  self という名前のメソッド(:to_i)を
# 残りの引数(16)を渡して呼びだします。

# つまりこれと同じ
# "A".to_i(16)
# ==> "A"を16進数にする

ここで覚える大切なこと :finnadie:

Symbol#to_procはselfに対応したこのProcのオブジェクトを返す

Proc.new{|obj, *args|, obj.send(self, *args)}

< Side Note >

Symbol#to_proc => Symbolクラスのインスタンスメソッドto_procということ

クラス名#インスタンスメソッド
クラス名.クラスメソッド

rubyのドキュメントではこういう表記をしてい松💝💀

&:メソッド を発明(?)した人(中二病想定)の気持ちになってみる

もっと魔術を.....ッッ!!!!😈 🦹♂️👿‍

(1..5).reduce{|previous, current| previous + current }

中二病だからとりあえず黒魔術のsend使ってみるか🔮

(1..5).reduce{|previous, current| previous.send(:+, current) }

中二病だからブロックが必要なメソッドなのに引数としてブロック渡そwww

(1..5).reduce(&Proc.new{|previous, current| previous.send(:+, current) })

# Procオブジェクトをブロックに変換する&(アンパサンド)を前置きして
# 引数でProcオブジェクトをブロックとして渡す

アレwww この形どっかで見たことあるぞっっwwwww

Proc.new{|previous, current| previous.send(:+, current) }

完全に一致!!!!!!!

# 上記例のreduceの引数で渡しているProcオブジェクト
Proc.new{|previous, current| previous.send(:+, current) }

# to_procで返るProcオブジェクトの中身
Proc.new{|obj, *args|, obj.send(self, *args)}

じゃあ :+ に to_proc 呼べばいいんじゃね☬✞

(1..5).reduce(&:+.to_proc)

to_procも書かなくていいんだったらもっとかっこいいんだけどなぁ...

こんな感じに...

(1..5).reduce(&:+)

return ポチ

irb(main):666:0> (1..5).reduce(&:+)
=> 15

う、≋う≋ご≋い≋た≋あ≋あ≋あ≋あ≋あ≋!≋!≋!≋!≋

なぜか!!?

ブロックを受け取るメソッドにProc以外が渡されると、暗黙的に to_proc を呼び出して型変換を行う仕組みがあるため

暗黙的とか超カッケーじゃん....🤤🤤🤤🤤

まとめ

そういうこと :fu:

インスパイア(参考)

RubyのSymbol#to_procを考えた人になってみる

5
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?