RubyのProcとは?ブロック・Proc・lamdaの違いをマスター
  • facebookページ
  • twitterページ
  • 2021.04.26

    RubyのProcとは?ブロック・Proc・lamdaの違いをマスター

    まずはブロックを理解しよう

    Procクラスを理解するには、Rubyのブロックを知っておく必要があるため、まずはブロックについてから解説していきます。

    ブロックとは、引数と一緒に渡すことのできる処理のかたまりです。 eachメソッドなどの繰り返しで使用されることが多いため、繰返し処理の中で行われる処理というイメージがあるかもしれませんが、それはブロックの1つの使い方であって、厳密には do~end{}で囲また処理をブロックと呼びます。

    ブロックの使い方

    ブロックの使い方を見ていきましょう。

    Rubyのブロックには、 do~endで処理を書く方法と {}で囲まれた中に処理を書く方法の2つの書き方が存在します。

    do~endで書くブロック

    {}(中括弧)で書くブロック

    どちらの書き方でもブロックであり、機能としては同じであるため、好みによってどちらを使っても構いません。ただし、一般的には処理が複数行に渡る場合は do~endで書き、処理が1行で済む場合は {}で囲う書き方を用います。

    ブロックはファイル入出力でも使用

    Rubyのブロックは、ファイルの入出力処理でも使います。

    File.openメソッドでファイルを開き、ブロックで開いたファイルに対する入出力の処理を定義します。そしてブロックを抜けるとファイルが自動でクローズされるため、閉じ忘れもなく処理を行えます。

    ブロックを引数で渡す

    ブロックをメソッドの引数として受け取り、渡されたブロックを実行するメソッドを定義できます。

    このようなメソッドを作ることで、メソッドの一部の処理を引数で受けとったブロックの処理で置き換えることが可能になり、ある部分までは共通化された処理で、一部だけ機能によって処理が異なる部分のメソッドを共通化しやすくなります。

    次のサンプルコードは、引数で渡されたブロックを10回実行して、その合計値を返すメソッドを定義する例です。

    このように、ブロックを受け取るメソッドでは block_given?でブロックが指定されているか判定し、ブロックの指定が省略された場合は、デフォルトの処理を通すようにするのが一般的です。

    Procとは

    それでは、本題のProcについて触れていきましょう。

    Procとは「ブロックをオブジェクト化したProcクラスのインスタンス」です。
    前章で解説したブロックを、ローカル変数のスコープやスタックフレームと共にオブジェクト化し、ブロックの代わりにメソッドの引数に渡すことができます。

    ブロックはその特性上、メソッドの引数に1つしか指定することができませんが、Procにオブジェクト化したブロックであれば、通常の変数と同じようにメソッドで複数渡すことも可能です。

    Procの作り方

    Procオブジェクトは、次の3つの方法で作ることができ、作成した Procオブジェクトの callメソッドより、指定したブロックの処理を実行することができます。

    1) procキーワードでブロックをProcオブジェクトに変換

    2) Procクラスのコンストラクタにブロックを指定してProcオブジェクトを作成

    3) メソッドの引数として渡す

    「&引数名」のようにメソッドの引数を宣言すると、呼び出し元で指定されたブロックが Procオブジェクトに変換され、メソッドの中で引数として渡されたブロックを callメソッドで呼び出すことができます。

    複数のProcをメソッドの引数として渡す

    Procはブロックをオブジェクト化したものであるため、他の数値や文字などの変数と同じ扱いになり、メソッドの引数としても複数渡せます。

    次のサンプルコードは、引数を2倍と3倍にする Procオブジェクトを2つ用意して、メソッドの引数として渡し、呼び出し先のメソッド内で2つの Procオブジェクトの処理をそれぞれ実行する例です。

    Procとlambda

    lambdaは、 Procオブジェクトを作るもう一つの方法ですが、 procキーワードや、 Proc.newで作成した Procオブジェクトとで、 returnの挙動が異なります。

    Proc.newでreturnした時

    Proc.newprocキーワードで作成した Procオブジェクトは、そのブロック内で returnをすると、呼び出し元のメソッドから抜けてしまいます。

    ポテパンダの一言メモ

    Proc.newprocキーワードで作成した Procオブジェクトで returnをする時、 callメソッドを呼んだメソッドを抜けるわけではなく、その Procを宣言したメソッドから処理が抜けることに注意が必要です。

    lambdaでreturnした時

    一方、 lambdaで作成した Procオブジェクトは、そのブロック内で returnをしても、呼び出ししたメソッドの処理に戻り、後続の処理が実行されます。

    まとめ

    Rubyのブロックと Procクラスについて解説してきました。ブロックの概念は最初は難しいかもしれませんが、Rubyを学ぶ上では避けてわ通りない道ですので是非理解しておきましょう。

    【関連記事】
    Rubyのlambdaとは?ブロックの使い方から詳しく解説



    優良フリーランス案件多数掲載中!
    フリーランスエンジニアの案件をお探しなら
    ポテパンフリーランス

    この記事をシェア

    • Facebookシェア
    • Twitterシェア
    • Hatenaシェア
    • Lineシェア
    pickup









    ABOUT US

    ポテパンはエンジニアと企業の最適なマッチングを追求する企業です。

    READ MORE