Ruby 1.9.2 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Procクラス
class Proc
クラスの継承リスト: Proc < Object < Kernel < BasicObject
Abstract
ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです。
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.#lambda と Proc.new はどちらも Proc クラスのインスタンス(手続きオブジェクト)を生成しますが、 生成された手続きオブジェクトはいくつかの場面で挙動が異なります。 lambda の生成する手続きオブジェクトのほうが よりメソッドに近い働きをするように設計されています。
Kernel.#proc は Proc.new と同じになります。 引数に & を付けることで手続きオブジェクト化したブロックは、Proc.new で生成されたそれと 同じにように振る舞います。
引数の扱い
lambda のほうがより厳密です。引数の数が違っていると(メソッドのように)エラーになります。 Proc.new は引数を多重代入に近い扱い方をします。
例:
b1 = Proc.new{|a,b,c| p a,b,c } b1.call(2, 4) #=> 2 4 nil b2 = lambda{|a,b,c| p a,b,c } b2.call(2, 4) #=> wrong number of arguments (2 for 3) (ArgumentError)
メソッド呼び出し も参照してください。
ジャンプ構文の挙動の違い
return と break は、lambda と Proc.new では挙動が異なります。 例えば return を行った場合、lambda では手続きオブジェクト自身を抜けますが、 Proc.new では手続きオブジェクトを囲むメソッドを抜けます。
例:
def foo f = Proc.new { return :foo } f.call return end def bar f = lambda { return :bar } f.call return end def h yield end def hoge h{ return :hoge } nil end p foo() #=> :foo p bar() #=> nil p hoge() #=> :hoge
以下の表は、手続きオブジェクトの実行を上の例と同じように、手続きオブジェクトが定義されたのと 同じメソッド内で行った場合の結果です。
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
-
ブロックをコンテキストとともにオブジェクト化して返します。
ブロックを指定しなければ、このメソッドを呼び出したメソッドが ブロックを伴うときに、それを Proc オブジェクトとして生成して返します。
def foo pr = Proc.new pr.call(1) end foo {|arg| p arg } # => 1
これは以下と同じです。
def foo yield(1) end foo {|arg| p arg } # => 1
呼び出し元のメソッドがブロックを伴わなければ、例外 ArgumentError が発生します。
def foo Proc.new end foo # => -:2:in `new': tried to create Proc object without a block (ArgumentError) from -:2:in `foo' from -:4
Proc.new は、Proc#initialize が定義されていれば オブジェクトの初期化のためにこれを呼び出します。このことを 除けば、Kernel.#proc と同じです。
インスタンスメソッド
self === obj -> ()
-
[SEE_ALSO] Proc#call
self[*arg] -> ()
call(*arg) -> ()
-
手続きオブジェクトを実行してその結果を返します。
引数はブロックの引数にそのまま(多重代入のルールに従い)代入されます。
- [PARAM] arg:
- 手続きオブジェクトに与える引数を指定します。
- [EXCEPTION] LocalJumpError:
- Procを生成したメソッドからリターンしてしまった場合に発生します。
arity -> Fixnum
-
Proc オブジェクトが受け付ける引数の数を返します。
ただし、可変長引数を受け付ける場合、負の整数
-(必要とされる引数の数 + 1)
を返します。
例:
lambda{ }.arity # => -1 lambda{|| }.arity # => 0 lambda{|x| }.arity # => 1 lambda{|*x| }.arity # => -1 lambda{|x, y| }.arity # => 2 lambda{|x, *y| }.arity # => -2 lambda{|(x, y)| }.arity # => 2 lambda{|(x, y), z|}.arity # => 2
binding -> Binding
-
Proc オブジェクトが保持するコンテキストを Binding オブジェクトで返します。
curry -> Proc
curry(arity) -> Proc
-
Procをカリー化します
カリー化したProcはいくつかの引数をとります。十分な数の引数が与えられると、元のProcに引数を渡し て実行し、結果を返します。引数の個数が足りないときは、部分適用したカリー化Procを返します。
- [PARAM] arity:
- 引数の個数を指定します
- [RETURN]
- カリー化したProcオブジェクトを返します
b = proc {|x, y, z| (x||0) + (y||0) + (z||0) } p b.curry[1][2][3] #=> 6 p b.curry[1, 2][3, 4] #=> 6 p b.curry(5)[1][2][3][4][5] #=> 6 p b.curry(5)[1, 2][3, 4][5] #=> 6 p b.curry(1)[1] #=> 1 b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) } p b.curry[1][2][3] #=> 6 p b.curry[1, 2][3, 4] #=> 10 p b.curry(5)[1][2][3][4][5] #=> 15 p b.curry(5)[1, 2][3, 4][5] #=> 15 p b.curry(1)[1] #=> 1 b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) } p b.curry[1][2][3] #=> 6 p b.curry[1, 2][3, 4] #=> wrong number of arguments (4 or 3) p b.curry(5) #=> wrong number of arguments (5 or 3) p b.curry(1) #=> wrong number of arguments (1 or 3) b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) } p b.curry[1][2][3] #=> 6 p b.curry[1, 2][3, 4] #=> 10 p b.curry(5)[1][2][3][4][5] #=> 15 p b.curry(5)[1, 2][3, 4][5] #=> 15 p b.curry(1) #=> wrong number of arguments (1 or 3) b = proc { :foo } p b.curry[] #=> :foo
lambda? -> bool
parameters -> [object]
-
Proc オブジェクトの引数の情報を返します。
source_location -> [String, Fixnum] | nil
-
returns the ruby source filename and line number containing this proc or nil if this proc was not defined in ruby (i.e. native)
to_proc -> self
-
self を返します。
to_s -> String
-
self の文字列表現を返します。
可能なら self を生成したソースファイル名、行番号を含みます。
p Proc.new { true }.to_s => "#<Proc:0x0x401a880c@-:3>"
yield(*arg) -> ()
-
Proc#call と同じですが、引数の数のチェックを行いません。
pr = Proc.new {|a,b,c| p [a,b,c]} pr.yield(1) #=> [1, nil, nil] pr.yield(1,2,3,4) #=> [1, 2, 3] pr.call(1) #=> wrong # of arguments (4 for 3) (ArgumentError)
これは yield と同じ動作です。
def foo yield(1) end foo {|a,b,c| p [a,b,c]}
- [PARAM] arg:
- 手続きオブジェクトに与える引数を指定します。
- [EXCEPTION] LocalJumpError:
- Procを生成したメソッドからリターンしてしまった場合に発生します。
[SEE_ALSO] メソッド呼び出し