ruby Method proc lambdaと閉パッケージ
6960 ワード
ProcとLambdaの違いは、主に: ProcとLambdaはオブジェクトですが、Blockは ではありません.パラメータリストには最大1つのBlockしかありませんが、複数のProcまたはLambda があります. Lambdaはパラメータの検査が厳格であるが,Procは比較的緩やかである ProcとLambdaのreturnキーワードの動作は異なる(Procでは周辺メソッドが直接返され、Lambdaではコードブロック内のみが返される) Proc動作はコードブロックに似ており、lambda動作と方法は に似ている.
簡単に述べる rubyのすべてのメソッドは、オブジェクトが関連付けられている真のメソッドです.rubyは、オブジェクトが関連付けられていないメソッドをobjectオブジェクトのプライベートメソッド と暗黙的に定義します. methordオブジェクトは、メソッド を表す procおよびlambdaは、いずれも閉パケット(proc動作とコードブロックが一致し、lambdaおよびメソッド動作が一致するが、その本質はコードブロックを表すオブジェクトである) を表すコードブロックを表すことができる.
procメソッド定義yieldキーワードを使用しない場合、&先頭のコードブロックパラメータで渡されるのはコードブロック{}、&後のパラメータはprocオブジェクト(callはprocオブジェクトのメソッド) メソッド定義yieldキーワードを使用しない場合、最後のパラメータは&先頭ではなく、最後のパラメータはcall関数を呼び出すことができ、procオブジェクト である.メソッド呼び出し時にprocオブジェクトの前で&を使用すると、procは通常のコードブロックとして使用され、&メソッド呼び出し時にすべてのサポートto_Procメソッドのオブジェクトの前に、to_が暗黙的に呼び出されます.Procはその後、 を通常のコードブロックとして使用する.
1.procオブジェクトを作成する3つの方法:
Lambdaの字面量のカッコは、以下のような書き方で選択できます.
2.Procとlambdaを呼び出す
lambda
Procとlambdaはメソッドではなくオブジェクトです.したがって,メソッドのように直接呼び出し,カプセル化されたコードを呼び出す方法はない.
Lambdaの使用例
Lambda閉パッケージの使用例:
MethodオブジェクトメソッドはMethodインスタンスで表すことができるが、Method呼び出しメソッドでは効率的ではない .
バインドされていないMethodオブジェクト
# proc
2.2.0 :094 > def my_func(n)
2.2.0 :095?> b = proc {|item| return item*n }
2.2.0 :096?> end
=> :my_func
2.2.0 :097 > my_func(2).class
=> Proc
2.2.0 :098 > my_func(2).call 5
LocalJumpError: unexpected return
from (irb):95:in `block in my_func'
from (irb):98:in `call'
from (irb):98
from /Users/atpking/.rvm/rubies/ruby-2.2.0/bin/irb:11:in `'
# lambda
2.2.0 :087 > def my_func(n)
2.2.0 :088?> b = lambda {|item| return item*n }
2.2.0 :089?> end
=> :my_func
2.2.0 :090 > my_func(2).call 5
=> 10
2.2.0 :091 > my_func(2).class
=> Proc
2.2.0 :092 >
簡単に述べる
proc
# 1. proc
def sequence(n, m, b)
b.call(n*m)
end
p = Proc.new {|x| p x}
sequence(5,2,p)
# 2. & ( proc &, )
# ,& ,ruby , yield
# & proc , & to_proc 。method , proc
a, b = [1,2,3], [4,5]
summation = Proc.new {|total, x| total+x}
sum = a.inject(0, &summation) # => 6
sum = b.inject(sum, &summation) # => 15
# symbol to_proc , & , ,
2.3.4 :133 > def sum(x,*y)
2.3.4 :134?> total = x
2.3.4 :135?> y.each{|nex| total+=nex}
2.3.4 :136?> total
2.3.4 :137?> end
=> :sum
2.3.4 :138 > sum(1,*[1,2,3])
=> 7
2.3.4 :139 > proc = :sum.to_proc
=> #<0x007f8e62818f88>
2.3.4 :140 > def sys_print
2.3.4 :141?> yield 1,1,2,3
2.3.4 :142?> end
=> :sys_print
2.3.4 :143 > sys_print &proc
=> 6 # 。。。
2.3.4 :144 > word = ['and','but','car']
=> ["and", "but", "car"]
2.3.4 :145 > uppercase = word.map &:upcase
=> ["AND", "BUT", "CAR"]
2.3.4 :147 > upc = :upcase.to_proc
=> #<0x007f8e6212ba40>
2.3.4 :148 > uppercase = word.map &upc
=> ["AND", "BUT", "CAR"]
2.3.4 :149 > uppercase = word.map {|w| w.upcase}
=> ["AND", "BUT", "CAR"]
2.3.4 :150 >
def makproc(&block)
block # proc ,
end
adder = makeproc{|x,y| x+y} # proc
adder.call 2,2 # => 4
1.procオブジェクトを作成する3つの方法:
# lambda
2.3.4 :156 > lambda = ->(x,y){x+y}
=> #<0x007f8e621e96a8>
2.3.4 :159 > lambda_b = lambda {|x,y| x+y}
=> #<0x007f8e621aae58>
2.3.4 :157 > proc = proc{|x,y| x+y}
=> #<0x007f8e621d1cd8>
2.3.4 :158 > proc = Proc.new {|x,y| x+y}
=> #<0x007f8e621c0848>
# proc{|x,y| x+y}:
# ruby1.8 Proc(lambda)
# ruby1.9 Proc.new proc
# lambda
#
#
->(key, value=2; i, j, k){}
Lambdaの字面量のカッコは、以下のような書き方で選択できます.
->x {x+1}
->x, y ;i, j, k {}
->x, y, fac = 2 {}
-> {}
2.Procとlambdaを呼び出す
proc_f = Proc.new {|x, y| x+y}
# call
proc.f.call 1, 2
#
proc_f[1, 2]
#
proc_f.(1, 2)
lambda
# lambda
lambda = ->(x, y){x+y}
lambda = ->x, y{x+y}
# lambda
lambda.call 2,3
lambda[2,3]
def compose(f, g)
->(x){ f.call(g.call(x)) }
end
succ = compose(->x{x+1}, ->x{x*x})
succ.call 4 # => 17: (4*4)+1
data.sort{|a,b| b-a}
#
data.sort &->(a,b){ b-a }
Procとlambdaはメソッドではなくオブジェクトです.したがって,メソッドのように直接呼び出し,カプセル化されたコードを呼び出す方法はない.
2.3.4 :156 > proc = ->(x,y){x+y}
=> #<0x007f8e621e96a8>
# call
2.3.4 :160 > proc.call 1,2
=> 3
#
2.3.4 :161 > proc[1,2]
=> 3
#
2.3.4 :162 > proc.(1,2)
=> 3
Lambdaの使用例
2.3.4 :163 > def created_lambda(n)
2.3.4 :164?> ->(array){array.collect {|x| x*n}}
2.3.4 :165?> end
=> :created_lambda
2.3.4 :166 > lambda_t = created_lambda 2
=> #<0x007f8e62821818>
2.3.4 :167 > lambda_t.call([1,2,3])
=> [2, 4, 6]
Lambda閉パッケージの使用例:
2.3.4 :173 > def accessor_pair(initialValue=nil)
2.3.4 :174?> value = initialValue
2.3.4 :175?> setter = ->(x){value = x}
2.3.4 :176?> getter = ->{value}
2.3.4 :177?> return getter,setter
2.3.4 :178?> end
=> :accessor_pair
2.3.4 :179 > getX,setX = accessor_pair("oldValue")
=> [#<0x007f8e6208e740>, #<0x007f8e6208e790>]
2.3.4 :180 > getX.call
=> "oldValue"
2.3.4 :182 > getX[]
=> "oldValue"
2.3.4 :183 > setX["newValue"]
=> "newValue"
2.3.4 :184 > getX[]
=> "newValue"
2.3.4 :185 > def muti(*arge)
2.3.4 :186?> arge.map {|x| lambda{|y| x*y}}
2.3.4 :187?> end
=> :muti
2.3.4 :188 > lam1,lam2 = muti 2,3
=> [#<0x007f8e622088a0>, #<0x007f8e62208850>]
2.3.4 :189 > lam1[2]
=> 4
2.3.4 :190 > lam1[3]
=> 6
Methodオブジェクト
# method
# method proc
# method ruby1.9
バインドされていないMethodオブジェクト
String.instance_method(:reverse).bind("hello").call
class Module
# instance_method
alias [] instance_method
end
#
String[:reverse].bind("hello").call
class UnboundMethod
alise [] bind
end
#
String[:reverse]["hello"][]
# [] [] []