【Ruby】Procオブジェクトの作成・実行方法まとめ

Ruby

Procについて

Procクラスはブロックをオブジェクト化するクラスです。
つまりProcオブジェクトとは、Procクラスを利用してオブジェクト化されたブロックのインスタンスのことを指します。

ブロック単体だけではオブジェクトとして定義できないため、ブロックをオブジェクト化したい場合にProcを利用します。

Procは『オブジェクトの生成 → オブジェクトの呼び出し』の手順で実行します。

Procオブジェクトの作成方法

Procオブジェクトの作成方法について紹介します。

引数なしのProcオブジェクト作成方法

引数なしの場合は以下のようになります。なお、ブロックを定義する際は{...}の代わりにdo ... endを利用してもOKです。

### Proc.new パターン
proc_example = Proc.new {
  # 処理
}

### proc パターン
proc_example = proc {
  # 処理
}

### -> パターン
proc_example = -> {
  # 処理
}

### lambda パターン
proc_example = lambda {
  # 処理
}

具体的には以下のようになります。

### Proc.new パターン
message_proc_new = Proc.new {
  "Hi"
}

### proc パターン
message_proc = proc {
  "Hi"
}

### -> パターン
message_arrow = -> {
  "Hi"
}

### lambda パターン
message_lambda = lambda {
  "Hi"
}

### 実行結果
message_proc_new.call
=> "Hi"
message_proc.call
=> "Hi"
message_arrow.call
=> "Hi"
message_lambda.call
=> "Hi"

引数ありのProcオブジェクト作成方法

### Proc.new パターン
proc_example = Proc.new do |引数|
  # 処理
end

### proc パターン
proc_example = proc do |引数|
  # 処理
end

### -> パターン
proc_example = -> (引数) {
  # 処理
}

### lambda パターン
proc_example = lambda do |引数|
  # 処理
end

具体的には以下のようになります。
なお仮引数と実引数の数が異なる場合、lambda->はエラーになり、Proc.newprocはエラーになりません。

### Proc.new パターン
message_proc_new = Proc.new do |name|
  "Hi #{name}."
end

### proc パターン
message_proc = proc do |name|
  "Hi #{name}."
end

### -> パターン
message_arrow = -> (name) {
  "Hi #{name}."
}

### lambda パターン
message_lambda = lambda do |name|
  "Hi #{name}."
end

### 実行結果(仮引数と実引数の数が一致している場合)
message_proc_new.call("Bob")
=> "Hi Bob."
message_proc.call("Bob")
=> "Hi Bob."
message_arrow.call("Bob")
=> "Hi Bob."
message_lambda.call("Bob")
=> "Hi Bob."

### 実行結果(仮引数と実引数の数が一致していない場合)
message_proc_new.call
=> "Hi ."
message_proc.call
=> "Hi ."
message_arrow.call
# ArgumentError: wrong number of arguments (given 0, expected 1)
message_lambda.call
# ArgumentError: wrong number of arguments (given 0, expected 1)

Procオブジェクトの実行方法

Procオブジェクトの実行方法について紹介します。

引数なしのProcオブジェクト実行方法

### call パターン
proc_example.call

### yield パターン
proc_example.yield

### .() パターン
proc_example.()

### [] パターン
proc_example[]

具体的には以下のようになります。

message_proc = proc {
  "Hi"
}

### call パターン
message_proc.call
=> "Hi"

### yield パターン
message_proc.yield
=> "Hi"

### .() パターン
message_proc.()
=> "Hi"

### [] パターン
message_proc[]
=> "Hi"

引数ありのProcオブジェクト実行方法

### call パターン
proc_example.call(引数)

### yield パターン
proc_example.yield(引数)

### .() パターン
proc_example.(引数)

### [] パターン
proc_example[引数]

具体的には以下のようになります。

message_proc = proc do |name|
  "Hi #{name}."
end

### call パターン
message_proc.call("Bob")
=> "Hi Bob."

### yield パターン
message_proc.yield("Bob")
=> "Hi Bob."

### .() パターン
message_proc.("Bob")
=> "Hi Bob."

### [] パターン
message_proc["Bob"]
=> "Hi Bob."

メソッド内でProcオブジェクトを実行する方法

Procオブジェクトをメソッドの引数にする場合はブロック引数(&)を利用します。

引数なしのProcオブジェクトを利用する場合

def example(&ブロック引数)
  ブロック引数.call
end

具体的には以下のようになります。

def message(&block)
  print "Hey Bob. "
  block.call
  print " to eat hamburgers."
end

message_proc = proc {
  print "Let's go to McDonald's"
}

message(&message_proc)
# Hey Bob. Let's go to McDonald's to eat hamburgers.

引数ありのProcオブジェクトを利用する場合

def example(引数, &ブロック引数)
  ブロック引数.call(引数)
end

具体的には以下のようになります。

def message(destination, &block)
  print "Hey Bob. "
  block.call(destination)
  print " to eat hamburgers."
end

message_proc = proc do |destination|
  print "Let's go to #{destination}"
end

message("McDonald's", &message_proc)
# Hey Bob. Let's go to McDonald's to eat hamburgers

ブロック引数の定義位置は引数の最後にする必要があります。
ブロック引数の仮引数の位置が最後でないと以下のようにシンタックスエラーとなります。

### ブロック引数の仮引数の位置が最後でないとシンタックスエラーになる
def message(&block, destination)
  print "Hey Bob. "
  block.call(destination)
  print " to eat hamburgers."
end
# SyntaxError: unexpected ',', expecting ')'

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考