Ruby/Rubyの基礎知識

ブロックとイテレータ、および手続きオブジェクトProcとlambdaについて(2ページ目)

Rubyの特徴的な文法であるブロックとイテレータについて解説を行います。標準イテレータのほか、自分でブロック付きメソッドを定義する方法、そして最後にブロックを手続きオブジェクトとして扱うProcとlambdaについて解説します。

橋本 拓也

執筆者:橋本 拓也

Rubyガイド

ブロック付きメソッドを定義する

前のページでは eachtimes といった標準のイテレータにブロックを渡して来ましたが、次はブロックを引数に取るメソッドを独自に定義してみましょう。

方法は簡単で、メソッド定義時に yield というキーワードを含めるだけです。yieldの箇所で渡したブロックが実行され、さらにyieldの使用回数に制限はありません。

非情に単純です。

ちなみに例の最後で示したように、ブロックが渡されない場合はyieldの部分でno block given (yield) (LocalJumpError)が発生します。これを避けるために Kernel.#block_given? を使い、ブロックが渡されたときはyieldを実行するが、ブロックが渡されないときは別の動作をする(例えば任意の例外を投げる)ようなメソッドを定義できます。

さらに進み、each などでお馴染みのブロック引数がある場合を見てみます。

「通常の引数」と「ブロック引数」が共存する場合は次のように書きます。

ブロックをオブジェクトとして扱う

さてここまで、ブロックは「引数なのにメソッド定義の引数リストには現れない」「yieldという特別なキーワードで実行される」など、ある意味「特別扱い」をされてきました。

次に「ブロックをオブジェクトとして扱うことができれば、より柔軟なコードが書けるのではないか」と考えを進めてみます。たとえば渡されたブロックをその場でyield実行する以外に、別のメソッドに渡して処理をたらい回しにしたり、などという使い方が想定できます。

実際、それは可能です。先に上げた iter をもとに例を示します。

iterの定義時に&bという「&」付きの特殊な引数を書いておきます。bの素性を調べてみると、Procというクラスのインスタンスであることがわかります。これが、ブロックを表現するオブジェクトの正体です。

ブロックをコンテキスト(ローカル変数のスコープやスタックフレーム)とともにオブジェクト化した手続きオブジェクトです。

class Proc | Ruby 2.1.0 リファレンスマニュアル

Procインスタンスに対しProc#callメソッドを呼び出すことでコードを実行させます。

また、Procインスタンスはブロック付きメソッドの引数で実体化させる以外に、他のクラスと同じくProc.newするか、Proc.newと同じ意味のKernel.#procを使うことでも作成できます。

次のページではProc.newと同じくProcインスタンスを生成する「lambda」を紹介し、Procとの差異について解説します。

  • 前のページへ
  • 1
  • 2
  • 3
  • 次のページへ

あわせて読みたい

あなたにオススメ

    表示について

    カテゴリー一覧

    All Aboutサービス・メディア

    All About公式SNS
    日々の生活や仕事を楽しむための情報を毎日お届けします。
    公式SNS一覧
    © All About, Inc. All rights reserved. 掲載の記事・写真・イラストなど、すべてのコンテンツの無断複写・転載・公衆送信等を禁じます