バナー画像

本記事では「ブロック」を解説します。

処理のほんの一部分を別の処理に置き換えたり、その他さまざまなことができます。

では共通関数やメソッド、クラスのオーバーライドと何がちがう?となりますよね。

ブロックの基本とその応用について、解説していきます。

本記事を読み終える頃には、処理を大きく変更することなく部分的に差し替えるなど、効率的にプログラミングできるようになっていますよ!

ブロックとは?

ブロックといえば、プログラミングの世界では一般的に{ }で囲われた部分を意味します。

Rubyにおいても、確かに同じように{ }で囲うこともあります。しかしブロックには「処理のかたまり」という以上の意味があります。

たいそうに聞こえますが、今までさんざん出てきたといえば驚かれるでしょうか?

繰り返し処理で普通に使ってきたブロック

繰り返し行う処理、eachで1から10までを表示させる場合です。

(1..10).each do |i|
	puts i
end

do 〜 endで囲まれた部分がブロックです。

このような書き方もあります。

(1..10).each { |i| 
	puts i 
}

1行で書くなら・・・

(1..10).each { |i| puts i }

いずれにせよ、受け取るための変数と、処理する内容を記述するかたまり、という感覚が分かってきたでしょうか?

ここで|i|に注目しましょう。

この受け取るための変数をブロック変数といいます。

処理を隠す

ブロックは他に、定型処理を隠すという使われ方があります。

前記事「【Ruby入門】入力と出力」の「6.ブロックでオープン、クローズを省略可」にて解説しましたが、ここで再度詳細を解説しましょう。

以下が本来のファイルのオープン処理です。

io = File.open("sample1.txt", "r") 

while line = io.gets
    puts io.lineno.to_s
end

io.close

ブロックを指定するとこうなります。

File.open("sample1.txt", "r") do |io|
    while line = io.gets
        puts line
    end
end

2番目の方は、openとcloseがないのがお分かりでしょうか?

Rubyのマニュアルを見てみましょう。

ブロックを指定して呼び出した場合は、Fileオブジェクトを引数としてブロックを実行します。ブロックの実行が終了すると、ファイルは自動的にクローズされます。ブロックの実行結果を返します。

とあります。ということは、File.openはブロックでない呼び出し方をされたときと、ブロックで呼び出されたときで動きがちがうということです。

しかもそれは、使う側が単に仕様に応じて選択するだけということです。

処理を一時的に変更する

ブロックは、処理を一時的に変更するときにも使います。

配列のソート(整列)を例にとります。

配列を何らかの規則にもとづきソートさせたいということはよくあります。

その規則性の数だけメソッドを作っていては、名前と種類、引数の数などを覚えるのが大変です。

よって、ソートする枠組みだけ用意して、規則はその都度決めようという考えに至ります。

それがメソッドにブロックを渡すことにより一時的に処理を変更する、という意味です。

上図は何も渡さなければ文字コード順にソートされますが、ブロックで要素間の関係を渡すと、その順にソートできるということを表現しています。

何らかの規則性を受け取るとそちらで上書き、といったイメージでしょうか。

実際にやってみましょう。

まずは、シンプルにソートさせます。

array = ["zoo", "zone", "zabix", "along", "bee", "function"]
p array.sort

[実行結果]

["along", "bee", "function", "zabix", "zone", "zoo"]

実はコレ、以下と同じ動きになります。

array = ["zoo", "zone", "zabix", "along", "bee", "function"]
p array.sort{|a, b| a <=> b}

実行結果は、先ほどと同じです。

ここで解説です。

「a <=> b」とは、以下の結果を返します。

 

 

ちょっと分かりにくいので、こう説明します。

要素1 <=> 要素2

 

 

この判定を使って、配列の要素を昇順にソートできます。

では次に、単語数の少ない順に並べましょう。

array = ["zoo", "zone", "zabix", "along", "bee", "function"]
p array.sort{|a, b| a.length <=> b.length}

[実行結果]

["zoo", "bee", "zone", "zabix", "along", "function"]

sortに対して、要素間の関係だけをブロックで渡してソートさせる、ということが理解できたでしょうか?

ブロックの部分を「{|a, b| b <=> a}」とするだけで逆順にソート、といった柔軟な対応ができます。

2項目間の関係をブロックで定義しましたが、必ずしも項目間の関係だけでなく、個々の要素に対しての操作も指定可能です。

array = ["zoo", "zone", "zabix", "along", "bee", "function"]
array.each{|a| p a.upcase}

[実行結果]

"ZOO"
"ZONE"
"ZABIX"
"ALONG"
"BEE"
"FUNCTION"

ブロックつきメソッドを独自に作る

今度は自分でブロックつきメソッドを作ってみましょう。

仕様は以下のとおりです。

 

 

まずは実行側です。

def calc_price(amount, price)
	result = 0
	if block_given?
		result = yield(amount * price)
	else
		result = amount * price
	end
end

そして呼ぶ側は以下です。まずは普通に数量×単価です。

p calc_price(5, 100)

[実行結果]

500

次に、消費税込みの金額を出しましょう。

p calc_price(5, 100){|num| num * 1.08}

[実行結果]

540.0

普通はこんな方法をとりませんが、ブロックを渡す・受け取って使う方法を確認するという観点から、あえてこのような例にしました。

解説

block_given?で、ブロックが与えられた場合はtrue、そうでないならfalseを得られます。ブロックがない場合は普通に数量と単価をかけています。

ブロックを得られれば「yield(amount * price)」にて受け取った数量と単価をかけて、その結果を受け取った計算方法に渡しています。

この場合、数量と単価をかけて、1.08をかけています。結果540円を得たということになります。

ブロックを渡す、つまりこの場合計算方法もろとも渡してしまう、というのが理解できたでしょうか?

計算方法は重要ではなく、計算方法そのものを「まるっと」渡している!ということに注目してください。

まとめ

本記事では、ブロックについて解説しました。

方法まるごと渡してしまう、この便利さに少しでも気づいていただけたなら幸いです。

先の例を使って、さまざまな計算方法を渡してみたりして遊んでくださいね!

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。