Procオブジェクトについて

f:id:ryoutaku_jo:20190810052629p:plain

【結論】

Procオブジェクトとは、ブロックをオブジェクト化したもの

・オブジェクト化することで、変数に代入してメソッドに引数として渡すなど、自由に扱うことが出来る

Proc.newproclambda->と複数の生成方法が存在する

【目次】

【本題】

Procオブジェクトについて

Procオブジェクトとは、ブロックをオブジェクト化したものです。

ブロックは、メソッド呼び出しの際に引数と一緒に渡すことのできる処理のかたまりです。

Rubyは、全てのデータをオブジェクトとして扱いますが、ブロックはあくまで「処理」なので、オブジェクトでは無いので、それ単体で存在することが出来ません

その為、一度定義したブロックを自由に呼び出せる様にするには、オブジェクト化する必要があります。

これにより、変数に入れてメソッドに渡したり、Procオブジェクトに対してメソッドを呼び出せる様になります

Procオブジェクトの使い方

Procオブジェクトの生成方法ですが、Proc.newにブロックを渡す方法があります。

Procオブジェクトのブロックを実行する場合は、callメソッドを利用します。

block = Proc.new { |i| i * 2 }

block.call(10)
=> 20

引数は、複数指定することも可能です。

block = Proc.new { |a, b| a * b }

block.call(10, 20)
=> 200

メソッドの引数として渡す場合は、引数名の頭に&を付けます。

メソッドに渡せるブロックは、一つまでです。

block = Proc.new { |i| puts i * 2 }

[1, 2, 3, 4, 5].each(&block)
=> 
2
4
6
8
10

なお、メソッドの引数としてではなく、普通に渡すことも出来ます。

この場合は、ブロックとしてカウントされないので、渡せる数に制限はありません

def blocks(block1, block2)
  puts block1.call(20, 10)
  puts block2.call(20, 10)
end

plus = Proc.new { |a, b| a + b }
minus = Proc.new { |a, b| a - b }

blocks(plus, minus)
=> 
30
10

Procオブジェクトの生成方法ごとの違い

Procオブジェクトの生成方法は、Proc.newproclambda->の4種類が存在します。

Proc.new { |n| n * n }

proc { |n| n * n }
lambda { |n| n * n }

->n{ n * n }

これらは、上の二つと、下の二つで、挙動が若干異なる部分があります。

それは、引数チェックの厳密さと、returnの挙動です。

引数のチェックに関しては、Proc.new引数の数が一致しなくてもエラーにならないのに対して、lambdaエラーになります

brock1 = Proc.new { |a, b| a + b }
brock1.call(1, 2, 3)
=> 3

brock2 = lambda { |a, b| a + b }
brock2.call(1, 2, 3)
=> ArgumentError (wrong number of arguments (given 3, expected 2))

また、Procオブジェクトの中でreturnを記述した場合、Proc.newはProcオブジェクトが生成されたメソッドを抜けます

対して、lambdaは、returnが実行されるてもブロックを抜けるだけで、メソッドの内の処理は継続して実行されます。

def hoge
  brock1 = Proc.new { return "hoge" }
  brock1.call
  return "hoge hoge"
end

def fuga
  brock2 = lambda { return "fuga"  }
  brock2.call
  return "fuga fuga"
end

puts hoge
=> hoge

puts fuga
= > fuga fuga

参考情報

Procを制する者がRubyを制す(嘘)

Ruby block/proc/lambdaの使いどころ - Qiita

https://docs.ruby-lang.org/ja/latest/class/Proc.html

Rubyの面白さを理解するためのメソッド、ブロック、Proc、lambda、クロージャの基本 (3/3):若手エンジニア/初心者のためのRuby 2.1入門(8) - @IT

《今日の学習進捗(3年以内に10000時間に向けて)》

開発中のCSVでのユーザー一括登録にて、エラーで登録出来ないユーザーが大量に発生した場合、ActionDispatch::Cookies::CookieOverflowが発生する不具合が見つかった。 原因は、エラー時にエラー箇所を、redirect_tonoticeに渡して、ポップアップで分かる様にしていたが、大量にエラーが発生した場合、Cookieの許容量を超えてしまうことにあった。 インスタンス変数に格納して、ビューに直接表示する方向で対応を進める。

CKEditorを活用した編集画面は、テンプレートやファイルアップロードなど、複数の機能が組み合わさっている為、編集領域にテキストを入力して保存可否を確認するだけの現状のテストでは、非常に心許ない。 JavaScriptが絡む処理が多いので、私にとってはハードルが高い作業だが、品質向上のため、テストコードを拡充させていきたい。

学習開始からの期間 :244日
今日までの合計時間:2334h
一日あたりの平均学習時間:9.6h
今日までに到達すべき目標時間:2228h
目標との解離:106h
「10,000時間」まで、

残り・・・「7666時間!」