【Ruby】ブロック(再)
ブロックとは
ブロックはメソッドを呼び出すときに記述でき、yield 式を使って任意のタイミング、回数実行することができます。また、for 式, if 式などはスコープが作成されないのに対し、ブロックは新たにスコープを作成します。
ブロックと yield
メソッドの中で yield を呼び出すと、受け取ったブロックを実行します。
def func x x + yield end func(1){ 2 + 1 } #=> 4
{ } で囲まれている部分がブロックです。このブロックは3を返し、メソッド func では x とブロックの実行結果( yield )を足した 4 が実行結果になっています。
{ } の代わりに do end で記述できます。ブロックが複数行の時に使うことが多いです。
func(1) do x = 2 x += 2 end #=> 5
ブロックを渡さない場合は例外が発生します。
func(1) #=> LocalJumpError: no block given (yield)
block_given? メソッドを用いて、ブロック付きで呼び出された場合にのみ行いたい処理を記述することができます。
def move puts 'walk' yield if block_given? puts 'stop' end move #=> walk stop move{ puts 'run' } #=> walk run stop
スコープの比較
for 式、if 式ではスコープが作成されないとのことでした。これは for 式や if 式の中で定義した変数が外から参照できるということになります。
for i in 2..4 bar = 1 end puts bar #=> 1 puts i #=> 4
if true hoge = 1 end puts hoge #=> 1
これに対しブロックは新たにスコープを作成します。 ブロック内で定義された変数を外から参照することは出来ません。
def hoge piyo = 1 end puts piyo #=> NameError
ブロックにはもう一つ重大な機能があります。ブロック生成時の変数をブロック内で参照でき、その変数の更新結果が外部に影響される、という機能です。
def foo y y + yield end x = 2 puts foo(1) { x+=2 } #=> 5 puts x #=> 4
ブロックの実行により、x の値を取得、更新しています。このときの x はブロック外の変数と同一の変数であり、値ではなく変数そのものが共有されていることになります。
このような対応付けはユーザから直接指定できず変更もできないので、代入ではなく束縛といいます。このように処理の生成時の環境を束縛するものは、一般的にクロージャと呼ばれます。
参考書籍
Ruby公式資格教科書 Ruby技術者認定試験 Silver/Gold対応 (EXPERT EXPASS)
- 作者: 増井雄一郎,小川伸一郎,(株)日立ソリューションズ藁谷修一,川尻剛,牧俊男,Rubyアソシエーション,CTCテクノロジー(株)監修
- 出版社/メーカー: 技術評論社
- 発売日: 2012/02/22
- メディア: 単行本(ソフトカバー)
- 購入: 5人 クリック: 204回
- この商品を含むブログ (10件) を見る
- 作者: Rubyサポーターズ,すがわらまさのり,寺田玄太郎,三村益隆,近藤宇智朗,橋立友宏,関口亮一
- 出版社/メーカー: 技術評論社
- 発売日: 2013/08/10
- メディア: 大型本
- この商品を含むブログ (21件) を見る