# 3. ブロック付きメソッド呼び出し

- 3.1 ブロック付きメソッド呼び出しとは何ですか
- 3.2 ブロック付きメソッド呼び出しにブロックを渡すにはどうすればいいですか
- 3.3 ブロックは呼び出したメソッドの中からどのように使われますか
- 3.4 `Proc.new`では手続きオブジェクトが作られませんが

## 3.1 ブロック付きメソッド呼び出しとは何ですか

ブロックや手続きオブジェクトを活用するメソッドをブロック付きメソッド呼び出しと呼びます。

制御構造(特にループ)の抽象化のために用いられたため、イテレータと呼ばれることもありますが、 単なるブロックの呼び出しなどiterate（繰り返し）を行わないような場合でも活用できます。

下記はイテレータとして作成されたメソッドを使用したケースです。

    data = [1, 2, 3]
    data.each do |i|
      print i, "\n"
    end

このコードの出力はこのようになります。

    $ ruby test.rb
    1
    2
    3

つまり`do`と`end`で囲まれたブロックがメソッドに渡され、メソッド内で使用されます。 メソッドeachはブロックをdataの各要素に対して繰り返し適用します。

これをCで書くと次のようになります。

    int data[3] = {1, 2, 3};
    int i;
    for (i = 0; i < 3; i++) {
      printf("%d\n", data[i]);
    }

`for`を使って書いた場合は繰り返し処理を自分で処理しなくてはなりませんが、 ブロック付きメソッド呼び出しの場合はメソッド側で処理するため、境界条件の判定ミスで バグが生まれる可能性が減少します。

また、`do`...`end`の代わりに`{`...`}`を使うこともできます。

    data = [1, 2, 3]
    data.each { |i|
      print i, "\n"
    }

このコードは先の例と全く同じ動作をします。ただし、`do`...`end`と `{`...`}`で動作が異なる場合があります。

    foobar a, b do .. end # foobar がブロック付きメソッドとして呼び出されます
    foobar a, b { .. }    # b がブロック付きメソッドとして呼び出されます

これは`{ }`の方が`do`ブロックよりも結合強度が強いためです。

## 3.2 ブロック付きメソッドにブロックを渡すにはどうすればいいですか

ブロック付きメソッドにブロックを渡すには、メソッドの後ろにブロックを置く 方法の他に、手続きオブジェクト(を指す変数、定数)の前に&を つけて引数として渡す方法があります。

## 3.3 ブロックは呼び出したメソッドの中からどのように使われますか

メソッドの中からブロックを使用するには、`yield`制御構造、ブロック引数、 `Proc.new`の3種類の方法で行うことができます。( Cで書かれた拡張ライブラリ の中では、`rb_yield`が使われます。)

`yield`の場合には、`yield`の後ろに続く引数が、ブロック パラメータとしてブロックに渡され、ブロックが実行されます。

ブロック引数は、メソッド定義の引数の最後に`&method`という形で 置かれ、メソッドの中で、`method.call(args...)`という形で呼ばれます。

`Proc.new`は、メソッドの中で使われたときには、引数としてそのメソッドに 渡されたブロックをとり、そのブロックを内容とする手続きオブジェクトを 生成します。`proc`または`lamda`も同様です。

    def a (&b)
      yield
      b.call
      Proc.new.call
      proc.call
      lambda.call
    end
    a{print "test\n"}

## 3.4 `Proc.new`では手続きオブジェクトが作られませんが

`Proc.new`は、ブロックを与えられないと手続きオブジェクトを生成できず、 エラーになります。メソッド定義の中で 使われるブロックなしの`Proc.new`は、メソッド呼び出しにブロックが与えられて いることを仮定しています。

link: [FAQ::ブロック付きメソッド呼び出し]
reverse link: [Ruby FAQ]