Vol.7 ~ブロック~

○ ブロック

コードブロックやイテレータブロックと呼ばれ、まとめて実行したいコードを集めたもの。

○ イテレータ

コレクション.イテレータメソッド{|変数| 処理内容}

要素を順に返すイテレータメソッド「each」

>> [1, 2, 3].each{|i| puts i * 10} # 各要素10を掛けて出力する
10
20
30
=> [1, 2, 3]

イテレータメソッドを呼び出すと、コレクションの要素がブロック内の「変数」に渡され、「処理内容」を実行する。
ハッシュの場合は、変数の部分が「キー」と「バリュー」の2つになる。

>> {:uno => 1, :dos => 2} .each do |key, val|
>> puts key
>> puts val
>> end
uno
1
dos
2
=> {:uno => 1, :dos => 2}

イテレータに限らず、後ろにブロックをつけてメソッドを呼び出すこの形を「ブロックつきメソッド呼び出し」という。

○ ブロックつきメソッドの実装

>> def threetimes
>>   if block_given? # ブロックが渡されたときに true となる
>>     yield "1!" # ブロックを実行するためのキーワード
>>     yield "2!"
>>     yield "3!"
>>   end
>> end
=> nil

>> threetimes{|n| puts n} # yield の後ろの文字列が n に渡される
1!
2!
3!
=> nil

○ Procオブジェクト

Ruby ではブロックをメソッドの後ろに配置することしかできない。
しかし、「Proc オブジェクト」を作成して「名づけ」をすると、あとからメソッドに渡すことが可能。

Proc オブジェクトを使用するには、以下の2つの手順が必要。

1) Procオブジェクトの作成

「Proc.new」の引数としてブロックを渡すことでProcオブジェクトを作成。

>> proc = Proc.new{|n| puts n}

または、

>> proc = lambda{|n| puts n}

2) Procオブジェクトを使ったメソッドの呼び出し。

作成したProcオブジェクトを、頭に「&」をつけてインテレータメソッドに渡す

>> [1, 2, 3].each &proc
1
2
3
=> [1, 2, 3]

○ クロージャとブロック

ブロックをある環境に結びつけることを「クロージャ」と呼ぶ。

>> # e の給料は amount よりも高いかどうか
>> def paidMore(amount)
>>   retunr Proc.new{|e| e.salary > amount}
>> end

>> #paidMore を呼び出す際に、引数 150 を設定して、戻り値である Proc オブジェクトを変数に代入
>> highPaid = paidMore(150)

これで、環境と結びついたブロック(クロージャ)の完成。
このクロージャは「e の給料は 150 よりも高いかどうか」という処理を行う。

クロージャの実際の使い方

>> # クラス Employee を、インスタンス変数 salary と定義
>> class Empoloyee
>>   attr_accessor :salary
>> end
=> nil
>> jon = Employee.new # インスタンス生成
=> #<Employee:0x2e66fd4>
>> john.salary = 200 # 値の設定
=> 200
>> highPaid.call(john) # クロージャ「highPaid」 をメソッド「call」で呼び出す
=> true # john の給料 200 は 150 より高いので ture

○ そのほかのブロックの使い方

ファイルIO などにも使用できる。
例えば、「File.open」にブロックを渡すと、ブロック終了時にファイルストリームのクローズを行ってくれるため、自分で管理する必要がない。

>> File.open("hello.rb") do |file|
>>   puts file.read # ファイルの中身を読み込む
>> end


自宅サーバーWebRing << 前 |ID=231 |次 >> 乱移動前後5表示サイト一覧