Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Procクラス

class Proc

クラス・モジュールの継承リスト: Proc < Object < Kernel < BasicObject

要約

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

Proc は ローカル変数のスコープを導入しないことを除いて名前のない関数のように使えます。ダイナミックローカル変数は Proc ローカルの変数として使えます。

Proc がローカル変数のスコープを保持していることは以下の例で変数 var を参照できていることからわかります。



var = 1
$foo = Proc.new { var }
var = 2

def foo
  $foo.call
end

p foo       # => 2

手続きを中断して値を返す

手続きオブジェクトを中断して、呼出し元(呼び出しブロックでは yield、それ以外では Proc#call) へジャンプし値を返すには next を使います。break や return ではありません。



def foo
  f = Proc.new{
    next 1
    2              # この行に到達することはない
  }
end

p foo().call       #=> 1

Proc オブジェクトをブロック付きメソッド呼び出しに使う

ブロック付きメソッドに対して Proc オブジェクトを `&' を指定して渡すと呼び出しブロックのように動作します。しかし、厳密には以下の違いがあります。これらは、Proc オブジェクトが呼び出しブロックとして振舞う際の制限です。

問題なし

(1..5).each { break }
LocalJumpError が発生します。

pr = Proc.new { break }
(1..5).each(&pr)

lambda と proc と Proc.new とイテレータの違い

Kernel.#lambdaProc.new はどちらも Proc クラスのインスタンス(手続きオブジェクト)を生成しますが、生成された手続きオブジェクトはいくつかの場面で挙動が異なります。 lambda の生成する手続きオブジェクトのほうがよりメソッドに近い働きをするように設計されています。

Kernel.#proc は Proc.new と同じになります。引数に & を付けることで手続きオブジェクト化したブロックは、Proc.new で生成されたそれと同じように振る舞います。

引数の扱い

lambda のほうがより厳密です。引数の数が違っていると(メソッドのように)エラーになります。 Proc.new は引数を多重代入に近い扱い方をします。

Proc.new は引数の数が違っていてもエラーにならない

b = Proc.new{|a,b,c|
  p a,b,c
}
b.call(2, 4)
#=> 2
    4
    nil
lambda は引数の数が違うとエラーになる

b = lambda{|a,b,c|
  p a,b,c
}
b.call(2, 4)
# => wrong number of arguments (given 2, expected 3)

メソッド呼び出し(super・ブロック付き・yield)/ブロックパラメータの挙動 も参照してください。

ジャンプ構文の挙動の違い

return と break は、lambda と Proc.new では挙動が異なります。例えば return を行った場合、lambda では手続きオブジェクト自身を抜けますが、 Proc.new では手続きオブジェクトを囲むメソッドを抜けます。



def test_proc
  f = Proc.new { return :from_proc }
  f.call
  return :from_method
end

def test_lambda
  f = lambda { return :from_lambda }
  f.call
  return :from_method
end

def test_block
  tap { return :from_block }
  return :from_method
end

p test_proc()   #=> :from_proc
p test_lambda() #=> :from_method
p test_block()  #=> :from_block

以下の表は、手続きオブジェクトの実行を上の例と同じように、手続きオブジェクトが定義されたのと同じメソッド内で行った場合の結果です。

               return                          next                        break
Proc.new   メソッドを抜ける            手続きオブジェクトを抜ける   例外が発生する
proc       メソッドを抜ける            手続きオブジェクトを抜ける   例外が発生する
lambda     手続きオブジェクトを抜ける  手続きオブジェクトを抜ける   手続きオブジェクトを抜ける
イテレータ メソッドを抜ける            手続きオブジェクトを抜ける   手続きオブジェクトを抜ける

orphan な手続きオブジェクトの挙動

Proc を生成したメソッドから脱出した後、手続きオブジェクトからの return, break は例外 LocalJumpError を発生させます。ただし、上でも説明した通り lambda で生成した手続きオブジェクトはメソッドと同じように振る舞うことを意図されているため、例外 LocalJumpError は発生しません。



def foo
  Proc.new { return }
end

foo.call
# => in `call': return from proc-closure (LocalJumpError)

以下の表は、手続きオブジェクトの実行を上の例と同じように、手続きオブジェクトが定義されたメソッドを脱出してから行った場合の結果です。

               return                          next                        break
Proc.new   例外が発生する              手続きオブジェクトを抜ける   例外が発生する
proc       例外が発生する              手続きオブジェクトを抜ける   例外が発生する
lambda     手続きオブジェクトを抜ける  手続きオブジェクトを抜ける   手続きオブジェクトを抜ける

特異メソッド

定義 説明
new -> Proc
new { ... } -> Proc

ブロックをコンテキストとともにオブジェクト化して返します。

インスタンスメソッド

定義 説明
self[*arg] -> ()
call(*arg) -> ()
self === *arg -> ()
yield(*arg) -> ()

手続きオブジェクトを実行してその結果を返します。

arity -> Integer

Proc オブジェクトが受け付ける引数の数を返します。

binding -> Binding

Proc オブジェクトが保持するコンテキストを Binding オブジェクトで返します。

curry -> Proc
curry(arity) -> Proc

Procをカリー化します

hash -> Integer

self のハッシュ値を返します。

to_s -> String
inspect -> String

self の文字列表現を返します。

lambda? -> bool

手続きオブジェクトの引数の取扱が厳密であるならば true を返します。

parameters -> [object]

Proc オブジェクトの引数の情報を返します。

source_location -> [String, Integer] | nil

ソースコードのファイル名と行番号を配列で返します。

to_proc -> self

self を返します。

継承したメソッド

! != __id__ __send__ instance_eval instance_exec method_missing singleton_method_added singleton_method_removed singleton_method_undefined !~ <=> == =~ _dump class clone define_singleton_method display enum_for eql? equal? extend freeze frozen? initialize initialize_copy instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself marshal_dump marshal_load method methods nil? object_id pretty_inspect pretty_print pretty_print_cycle pretty_print_inspect pretty_print_instance_variables private_methods protected_methods psych_to_yaml public_method public_methods public_send remove_instance_variable respond_to? respond_to_missing? send singleton_class singleton_method singleton_methods taint tainted? tap to_a to_ary to_hash to_int to_io to_regexp to_str trust untaint untrust untrusted? .yaml_tag ::ARGF ::ARGV ::DATA ::ENV ::FALSE ::NIL ::RUBY_COPYRIGHT ::RUBY_DESCRIPTION ::RUBY_ENGINE ::RUBY_ENGINE_VERSION ::RUBY_PATCHLEVEL ::RUBY_PLATFORM ::RUBY_RELEASE_DATE ::RUBY_REVISION ::RUBY_VERSION ::SCRIPT_LINES__ ::STDERR ::STDIN ::STDOUT ::TOPLEVEL_BINDING ::TRUE