Procって何？

## はじめに
```Proc```って知ってますか？僕は知らないです。

```ruby
    scope :old, -> { where('year_published < ?', 50.years.ago )}
```
Railsだと、上記のように```model```に```scope```を定義したりしますが、これは```lambda```によって```Proc```オブジェクトが生成されています。
Railsを触っていると```Proc```にはちょくちょく出会うので、出会った時にビビらないようにまとめたいと思います。

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

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

らしいです。処理自体をオブジェクトにすることができます。

**Proc**は**Procedure**を意味しています。

```ruby
    square = Proc.new{|a| a ** 2}
    square.call(8) # => 64
```
例えば上記のような例を考えた場合、変数```square```には```a(引数)を二乗する```という処理が入ります。
呼び出したい時は```callメソッド```を使うことで呼び出すことができます。

## Procオブジェクトの作り方
```ruby
    proc1 = Proc.new{|x| x * 2}
    # => #<Proc:0x00000001076f1af0 (irb):24>
    proc2 = proc {|x| x * 2}
    # => #<Proc:0x0000000107620568 (irb):25>
    proc3 = lambda{|x| x * 2}
    # => #<Proc:0x0000000107182678 (irb):26 (lambda)>
    proc4 = -> (x) { x * 2}
    # => #<Proc:0x0000000102e1f7a0 (irb):27 (lambda)>
```
↓ ```lambda```によって生成した場合の```Proc```オブジェクトの性質は少し異なります。

https://ruby-doc.org/core-2.7.1/Proc.html

>- In lambdas, return and break means exit from this lambda;
>- In non-lambda procs, return means exit from embracing method (and will throw LocalJumpError if invoked outside the method);
>- In non-lambda procs, break means exit from the method which the block given for. (and will throw LocalJumpError if invoked after the method returns);
>- In lambdas, arguments are treated in the same way as in methods: strict, with ArgumentError for mismatching argument number, and no additional argument processing;
>- Regular procs accept arguments more generously: missing arguments are filled with nil, single Array arguments are deconstructed if the proc has multiple arguments, and there is no error raised on extra arguments.

## メソッドとの違い
メソッドとの大きな違いは、```Proc```は```Object```にバインドされていないところだと思います。

```Ruby```は第一級関数を持たず、関数をデータとして扱いません。
そのため、メソッドには必ずレシーバがあり、なんらかの```Object```にバインドされています。

https://jp.quora.com/Ruby-ha-kansuu-kata-gengo-da-to-omoi-masu-ka

https://developer.mozilla.org/ja/docs/Glossary/First-class_Function

一方で```Proc```の場合は、レシーバを必要としないため第一級関数のように使うことができます。

```ruby
    [1] pry(main)> def hello
    [1] pry(main)*   puts "hello"
    [1] pry(main)* end  
    # => :hello
    [2] pry(main)> method(:hello).receiver
    # => main
    [3] pry(main)> hello_proc = Proc.new{puts "hello"}
    # => #<Proc:0x0000000109a9dda0 (pry):6>
    [4] pry(main)> hello_proc.receiver
    # NoMethodError: undefined method `receiver' for #<Proc:0x0000000109a9dda0 (pry):6>
```


https://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods

https://blog.appsignal.com/2018/09/04/ruby-magic-closures-in-ruby-blocks-procs-and-lambdas.html

## 参考にしたサイト

https://www.codewithjason.com/ruby-procs/

https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4774193976