Webサイト制作コースのお申し込みはこちら

前記事「【Ruby入門】ブロック」では、ブロックの基本を解説しました。

ブロックとは、処理そのものを部分的にまとめ、投げることができるものでしたよね?

ブロックが理解できたなら、さらに先に進みましょう!

本記事ではProcクラスの使い方や、ラムダ(lambda)まで解説します。

本記事を読み終えると、ブロックやラムダ式、クラスを効率的に使いこなすことができますよ!

ブロックとProcクラス

ブロックとは一連の手続きをまとめて投げるもの、と解説しました。

投げるだけでなく、さらに応用が利くようにできるのです。

そのときに使うのがProcクラスです。

Procクラスの使い方

まずコードから。

sayhello = Proc.new do |name|
	puts "Hello! #{name}"
end

呼び出すときはこうします。

sayhello.call("potepan")

[実行結果]

Hello! potepan

何が起こったのかというと、sayhelloという名前で、受け取った引数をputsで表示する「手続き」を持つオブジェクトができたのです。

sayhelloという名前の、Procオブジェクトにある手続きを呼ぶのがcallです。

callはProcクラスがもとから持っているメソッドなので、私たちはそれについて考える必要はありません。

Procオブジェクトを作るときに、do〜endで囲われたブロックを渡しています。

作ったオブジェクトの中の手続きを呼び出すときの引数がブロック引数となります。

総合すると、先ほどのプログラムはこうなります。

 

 

そして最後に「sayhello.call(“potepan”)」として結果を受け取ったというわけです。

オブジェクトというと、どうしても変数やメソッドを格納するというイメージがあります。

ここでちょっとパラダイムシフトして、手続きを持つオブジェクト、という理解をしてください。

難しいけど、そのうちハッと気づくときがきっと来ます。

また、呼び出すときはcallメソッドの他に、[]で書く方法もあります。

sayhello["potepan"]

引数はハッキリ決まってなくとも良い

引数の数が仕様上決まらないときは、ブロック変数を「|*配列|」の形式にして配列で受け取ることができます。

upsample1 = Proc.new do |*args|
	args.each do |str|
		p str.upcase
	end
end

upsample1.call("a", "b", "c")

[実行結果]

"A"
"B"
"C"

今のところは3つですが、増減しても問題なく動作します。

ラムダ(lambda)

ラムダ(lambda)も手続きを持つオブジェクトを作成できますが、Proc.newと比較して何点か異なる性質があります。

順に解説していきます。

ラムダとは何か

Ruby以外の言語でも、ラムダは普通にあります。ただし、ラムダ式と「式」が付きます。

いずれにしても、手続きを持って運ぶという意味は変わりません。

Procオブジェクトを作る手段をProc.newとラムダのいずれを使うか、という感じです。

ラムダの使い方

ラムダとProc.newのちがいを見ていきましょう。

ちがいに注目するので、内容は超簡単なものにしました。

upsample3 = lambda do |para1, para2, para3|
	p para1.upcase
	p para2.upcase	
	p para3.upcase
end

upsample3.call("a", "b", "c")

[実行結果]

"A"
"B"
"C"

Proc.newをラムダに置き換えただけですね。

復習のために、Proc.newバージョンも見ておきましょう。

upsample2 = Proc.new do |para1, para2, para3|
	p para1.upcase
	p para2.upcase	
	p para3.upcase
end

upsample2.call("a", "b", "c")

実行結果は同じです。

ラムダとProc.newの比較

前章で、ちがいは書き方くらいかなと思われたでしょうか?

ではなぜ2つ存在しているのか、2つのちがいは何か、というのを解説します。

引数の数が厳密になる

引数の数が厳密になります。Proc.newは数が異なっていてもエラーになりません

sample1 = Proc.new do |para1, para2, para3|
	p para1
	p para2	
	p para3
end

sample1.call("a", "b")

[実行結果]

"a"
"b"
nil

数が合わないなりに、なんとか動きます。

一方ラムダではそうはいきません。

sample2 = lambda do |para1, para2, para3|
	p para1
	p para2	
	p para3
end

sample2.call("a", "b")

[実行結果]

wrong number of arguments (given 2, expected 3) (ArgumentError)

引数の数が、本来は3なのに2個しか来てない!と怒られてしまいました。

ただし配列にすれば問題ありません。

sample3 = lambda do |*para|
	p para[0]
	p para[1]	
	p para[2]
end

sample3.call("a", "b")

[実行結果]

"a"
"b"
nil

returnが使える

ブロックから値を返すときに、returnを使ったときの挙動が異なります。

まずはラムダからです。

def sample4(greeting)
	lambda do |x|
		return greeting + x + "さん"
	end
end

morning = sample4("おはよう!")
p morning.call("honda")

[実行結果]

"おはよう!hondaさん"

次に、Proc.newです。

def sample5(greeting)
	Proc.new do |x|
		return greeting + x + "さん"
	end
end

morning = sample5("おはよう!")
p morning.call("honda")

[実行結果]

unexpected return (LocalJumpError)

若干強引な解説をします。

ラムダの場合、returnしたところでブロックはまだ生き残ったままです。

よって、「morning = sample4(“おはよう!”)」を終えてもまだ生きているために、次の「p morning.call(“honda”)」に来ても実行可能です。

ところがProc.newの場合はそうではありません。

returnした段階でオブジェクトが消えてしまい、次の「p morning.call(“honda”)」ではすでにブロックは消滅した後です。

よって、すでに消滅してしまったmoriningに対してcallを実行しようとしてエラーになったというわけです。

まとめ

本記事ではブロック、とりわけlambdaとProcについて解説しました。

両者をうまく使い分けて、効率的なプログラミングができるようになってくださいね!

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

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

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

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

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

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

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

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

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

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

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