2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本CTO協会24卒Advent Calendar 2024

Day 17

【Ruby】&:メソッド名 × yield を完全に理解したい

Last updated at Posted at 2024-12-17

はじめに

こちらはアドベントカレンダー17日目の記事です。

本記事では、Rubyでよく見かける「&:メソッド名」という記法とyieldの組み合わせについて解説します。

結論

ブロック付きメソッド内部でyieldを引数を渡して実行すると、第一引数をレシーバとして「&:メソッド名」のメソッドを実行する。

「&」とは?

RubyではProcオブジェクトをあらかじめ作っておき、後からブロック付きメソッドに渡すことができます。

Procオブジェクトをブロック付きメソッドに渡すには「&」をProcオブジェクトの先頭につける必要があります。

method(arg1, arg2, ..., &proc_object)

うーん、じゃあよく見るこれ何だ? proc_objectじゃないやん!と突っ込みたくなります。

irb(main):001> array = ["hoge", "fuga", "Bar"]
=> ["hoge", "fuga", "Bar"]
irb(main):002> array.map(&:upcase)
=> ["HOGE", "FUGA", "BAR"]

実は、to_procメソッドを持つオブジェクトであれば「&」を先頭につけてブロック引数として利用することができます。:upcaseはSymbolオブジェクトです。Symbolクラスにはto_procメソッドが定義されているのでその条件を満たします。

irb(main):001> :upcase.class
=> Symbol
irb(main):002> :upcase.class.method_defined?(:upcase)
=> true

to_procメソッドはメソッド呼び出し時に実行されます。

:メソッド名 と to_proc

ほう。Symbolオブジェクトがto_procでProcオブジェクトになるならcallしたらどうなる?と思い実験。

irb(main):001> proc_object = :upcase.to_proc
=> #<Proc:0x0000000106a51ae8(&:upcase) (lambda)>
irb(main):002> proc_object.call
(irb):2:in `<main>': no receiver given (ArgumentError)

レシーバが与えられてないと怒られてしまいましたね😇

実は、Symbolクラスのto_procによって生成されるProcオブジェクトはProc#callの第一引数をレシーバとして「:メソッド名」の「メソッド名」を実行します。

以下の例では、"Fuga"をレシーバとしてupcaseメソッドが実行されていることがわかります。

irb(main):003> proc_object.call("Fuga")
=> "FUGA"

yieldについて

yieldはブロック付きメソッド内でブロックを呼び出す際に利用します。yieldに引数を渡すと、その値はメソッドに渡されたブロックの引数としてブロック実行時に利用されます。

これを応用すると、Proc#callのレシーバをメソッド内で指定してブロックの処理を実行することができます。

irb(main):001* def fuga
irb(main):002*   yield("fuga")
irb(main):003> end
=> :fuga
irb(main):004> fuga(&:upcase)
=> "FUGA"

mapの実装

ちなみにArray#mapの実装を読むと、配列の要素であるvalueyieldの引数として渡しており、これによって配列の各要素がレシーバとなってメソッドが実行されるということになります。

result << yield(value)

参考

https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html#block
https://docs.ruby-lang.org/ja/latest/method/Symbol/i/to_proc.html

2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?