Search

検索したいワードを入力してください

2019年04月10日

Rubyのyeildを使おう!基礎から応用まで解説

Rubyには、Arrayクラスのmap、sortなど、ブロックを指定して使うメソッドが多くあります。これらのようなメソッドは、yieldを使用すると定義が可能です。本記事では、yieldのメソッド内での使い方、ブロック変数の指定などについて解説します。

yieldの基本的な使い方から応用までを解説

Rubyでは、Array#map、sortなど、ブロックを指定することができるメソッドが多く提供されています。これらのようなブロックを使用するメソッドは、メソッドにyieldを使用してブロックを受け取るようにすると、自分で定義することができます。

Rubyにおけるyieldの意味

yieldは英語で、(農作物を)産出する、という意味があります。Rubyにおいては、定義したメソッド内で、「指定したブロックを受ける部分」という意味で記述することができ、yieldの部分にブロック内に記述した処理が埋め込まれます。ブロック変数を指定した場合は、yield(x)のように関数のように扱うこともできます。

yieldの基本的な使い方

ブロックは、任意の関数をメソッドへ渡すのに使用することができます。以下のRubyスクリプトでは、数列の合計を求めるΣ(シグマ)を、yieldを使用してsigmaメソッドとして実装しています。

サンプルコード



def sigma(m,n)
sum=0
for i in m..n
sum+=yield(i)
end
sum
end

p (sigma(1,100) do |k| 2*k+3 end) #=> 10400
p (sigma(1,100) do |k| 4*k**2+3*k+1 end) #=> 1368650

yieldの応用

メソッド内でblock_given?を使用すると、メソッドにブロックを与えなかった場合の処理も記述することができます。以下のRubyスクリプトでは、座標平面上にある点の集合を、ある関数のグラフで上下に分離するメソッドseparateを定義しています。ブロックを与えなかった場合は、関数y=xについて分離されます。

#*** separate.rb ***
#separate.rb <サンプル点数> (<乱数の種>)で実行

def separate(points)
points.partition{|p|p[1]>(block_given? ? yield(p[0]):p[0])}
end

begin
n_points=Integer(ARGV[0])
raise unless n_points>0
rescue
abort"サンプル点数が無効です: #{ARGV[0]}"
end

if ARGV[1]
begin
seed=Integer(ARGV[1])
rescue
abort"乱数の種が無効です: #{ARGV[1]}"
end
else
seed=Random.new_seed
end

r1=Random.new(seed)

points=[]
n_points.times do
points<<[r1.rand,r1.rand]
end

low,high=separate(points){|x|x**2}
puts"--- y=x**2 ---"
puts"<上部> #{high.length}点"
puts high.each_slice(5).to_a.map{|block|block.map{|p|"(%.2f, %.2f)"%p}.join(", ")}.join(",\n")

puts

puts"<下部> #{low.length}点"
puts low.each_slice(5).to_a.map{|block|block.map{|p|"(%.2f, %.2f)"%p}.join(", ")}.join(",\n")

puts

low,high=separate(points)
puts"--- y=x ---"
puts"<上部> #{high.length}点"
puts"<下部> #{low.length}点"

実行結果

$ ruby separate.rb 60 27
--- y=x**2 ---
<上部> 22点
(0.89, 0.21), (0.78, 0.16), (0.74, 0.48), (0.97, 0.58), (0.70, 0.39),
(0.92, 0.49), (0.60, 0.26), (0.99, 0.21), (0.91, 0.12), (0.91, 0.24),
(0.98, 0.30), (0.90, 0.10), (0.46, 0.19), (0.74, 0.18), (0.83, 0.51),
(0.94, 0.39), (0.94, 0.48), (0.90, 0.76), (0.40, 0.07), (0.56, 0.21),
(0.94, 0.62), (0.95, 0.31)

<下部> 38点
(0.43, 0.81), (0.74, 0.87), (0.38, 0.98), (0.74, 0.66), (0.89, 0.86),
(0.75, 0.87), (0.19, 0.33), (0.37, 0.79), (0.15, 0.17), (0.08, 0.31),
(0.07, 0.70), (0.18, 0.60), (0.42, 0.51), (0.22, 0.73), (0.85, 0.93),
(0.49, 0.59), (0.08, 0.12), (0.09, 0.01), (0.84, 0.91), (0.71, 0.92),
(0.29, 0.68), (0.52, 0.88), (0.58, 0.65), (0.68, 0.75), (0.67, 0.87),
(0.56, 0.47), (0.02, 0.39), (0.21, 0.21), (0.40, 0.98), (0.19, 0.85),

(0.17, 0.46), (0.22, 0.51), (0.72, 0.95), (0.04, 0.98), (0.71, 0.73),
(0.40, 0.56), (0.71, 0.72), (0.11, 0.73)

--- y=x ---
<上部> 27点
<下部> 33点

ブロック内でbreakやnextを使用するときの注意

メソッドに渡したブロック内でも、breakやnextを使って制御することができます。ただし、記述した処理がそのままyieldに配置されるわけではなく、Rubyにおける従来のループとは振る舞いが異なります。これについて詳しく解説します。

breakを使用する場合

breakを使用すると、呼び出しメソッドの途中で中断することになります。よって、yieldが記述されている部分より先は実行されません。値を返すメソッドの場合、メソッドは最後まで到達せず、戻り値は必ずnilとなります。ただし、"break 0"のように記述するとその値をメソッドの戻り値として指定することができます。

以下のRuby文は、前述の数列の和を計算するスクリプトにおいて、メソッドsigmaを呼び出した場合です。

p (sigma(1,100) do |k| break if k==10 k**2 end) => nil
p (sigma(1,100) do |k| break 0 if k==10 k**2 end) => 0

nextを使用する場合

nextを使用すると、その回のブロックだけ、戻り値がnilとなり、その後の処理は継続されます。ただし、"next 0"のように指定した場合はそれがブロックの戻り値となります。

以下のRuby文では、以下は、前述の数列の和を計算するスクリプトにおいて、数列の奇数番目だけの和を計算します。ここで"next 0"を"next"とした場合、Integerとnilとの計算となるため、例外(TypeError)を起こして停止します。

p (sigma(1,100) do |k| next 0 if k%2==0;k**2 end) #=> 166650

yieldは関数をメソッドへ渡すときに便利

Rubyでは、ブロックを与えて、そこに記述された処理をメソッド内のyieldで受け取ることができます。ブロック内で、ブロック変数を指定すると、関数をメソッドへ渡すのに使用することができます。また、block_given?を使用すると、ブロックを与えなかった場合の処理も実装することができます。

ブロックの中ではbreakやnextも使えますが、従来のループとは振る舞いが異なることに注意しましょう。

【PR】多くの人がプログラミングを諦めてしまう理由をご存知ですか?



近年プログラミングを勉強する人が増えています。

プログラミング学習者の多くは独学から取り組もうとしますが、だいたい80%ほどは3ヶ月も続かずに諦めてしまいます。早い人は1日目で。

多くの人がプログラミングを独学しようとして諦める理由は、次の3つ。
●モチベーションが維持できない
●エラーの原因・解決方法が分からない
●どう学習すればよいか分からない

TechBoostというプログラミングスクールでは、みんなと一緒にプログラミングをするのでモチベーションの維持ができ、分からないことがあればマンツーマンで教えてくれ、徹底的に研究された初心者向けの教材が揃っています。

TechBoostを卒業後、実際にエンジニアとして転職した方もいるほど。

本気でプログラミングを学びたい方は、一度無料のカウンセリングでご相談ください。プログラミングを嫌いになる前に。

tech boostについて

オーダーメイド型の学習コンテンツを提供する「tech boost」 は、エンジニアのキャリア支援に特化したサービスを複数展開している株式会社Branding Engineerが運営しているプログラミングスクールです。最短3ヶ月間で、未経験から『プログラミングの基礎』、『実際に業務で必要となるスキル』、『今のトレンドとなっている知識』まで学べ、ご希望の方にはプロのキャリアアドバイザーによる就業支援を行うことができます。

tech boost卒業生インタビュー

tech boostの卒業生の声を聞きました。あなたがプログラミングを学びたい理由を、一度考えてみてください。
営業→Javaエンジニア→Rubyエンジニアと転向し、第一志望のFinTech企業で働く山下さん
元営業、ビジネスのわかるエンジニアを目指す菅原さん
サンフランシスコに交換留学し、シリコンバレーのVCでインターン中の梅本さん
予備校の営業から半年でエンジニア転職を果たした小田島さん

tech boostの口コミ



Related