2010년 05월 09일
The Ruby Proc
출처: Strugglig with Ruby
In Ruby a
The code in the Proc object can be invoked by using the call method.
You can pass around Proc objects like any other object:
Instead of using call, you can invoke the code using square brackets notation. The following are equivalent:
Proc.new vs lambda
If you call a Proc with too few arguments, Ruby will pad them out with the nil object, so multiply.call(14) above would invoke the Proc code with 14 and nil (which would generate an error in this case). Any extra arguments are simply discarded.
The
Using return in a Proc
Using an explicit
It seems that the
http://innig.net/software/ruby/closures-in-ruby.rb
API for the Proc object:
http://www.ruby-doc.org/core/classes/Proc.html
See also:
http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/
http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html
읽어보면 알게되겠지만, Proc과 Lambda는 둘 다 a type of block이지만, Proc는 object이고 Lambda는 block 모양의 function이다. 쓰임새면에서 놓고보면, Lambda가 더 powerful한 능력을 보여주지만 상대적으로 부하가 크고, Proc는 block형태의 객체로써, 비록 Lambda보다 그 쓰임새가 한정적이지만 더 가볍고 빠르다.
결국, 먼저 Proc을 고려하되 안되면 Lambda를 사용하는 것이 성능면에서 좋은 선택이 될 것 같다.
결국, 먼저 Proc을 고려하되 안되면 Lambda를 사용하는 것이 성능면에서 좋은 선택이 될 것 같다.
In Ruby a
Proc (short for procedure) is a block of code, bound to a variable (closely related to a block, discussed here). As is always the way in Ruby, a Proc is an object, and so can be created with the new method, though, as discussed later, it is generally preferable to use the lambda method. Here are some examples (expanding on those in the Ruby documention):# A Proc can have one, none or many arguments
times7 = Proc.new {|n| n * 7 }
statement = Proc.new { 'from statement' }
multiply3 = Proc.new {|x, y| x * y }
The code in the Proc object can be invoked by using the call method.
p times3.call(12) #=> 36
p times5.call(5) #=> 25
p times7.call(8) #=> 56
p times3.call(times5.call(4)) #=> 60
p statement.call #=> "from statement"
p multiply.call(4, 3) #=> 12
You can pass around Proc objects like any other object:
def gen_times(factor)
return Proc.new {|n| n*factor }
end
class ProcTest
# Class variable is a Proc
@@times13 = Proc.new {|n| n * 13 }
# Method uses various Proc objects
def test
times11 = Proc.new {|n| n * 11 }
p times11.call(3)
p @@times13.call(7)
times2 = gen_times(2)
p times2.call(19)
end
# Method uses a Proc passed as an argument
def test_argument prc
p prc.call(4)
end
end
# ProcTest object instantiated, and methods called
pt = ProcTest.new
pt.test
pt.test_argument Proc.new {|x| x + 5}
Instead of using call, you can invoke the code using square brackets notation. The following are equivalent:
multiply.call(4, 3)
multiply[4, 3]
Proc.new vs lambda
If you call a Proc with too few arguments, Ruby will pad them out with the nil object, so multiply.call(14) above would invoke the Proc code with 14 and nil (which would generate an error in this case). Any extra arguments are simply discarded.
The
Kernal has a method lambda (there is also a method proc, which reportedly does the same as Proc.new, but I found it identical to lambda) which will also give a Proc object, but in this case the Proc will raise an ArgumentError is the argument count is wrong.count_nils_new = Proc.new {|x, y, z|
"#{x.nil?} #{y.nil?} #{z.nil?}"
}
count_nils_lambda = lambda {|x, y, z|
"#{x.nil?} #{y.nil?} #{z.nil?}"
}
# The 4 is quietly discarded
p count_nils_new.call(1, 2, 3, 4)
# The method is sent 1, 2, nil
p count_nils_new.call(1, 2)
# The method is sent nil, nil, nil
p count_nils_new.call
# This is fine
p count_nils_lambda.call(1, 2, 3)
# These will all generate an ArgumentError
p count_nils_lambda.call(1, 2, 3, 4)
p count_nils_lambda.call(1, 2)
p count_nils_lambda.callProc objects have an arity method that can be used to determine how many arguments the Proc is expecting.Using return in a Proc
Using an explicit
return in a Proc object created with Proc.new (but not lambda) will cause the calling method to return that value.def with_return_and_new
prc = Proc.new { return 'This is printed' }
prc.call
'Never seen'
end
def no_return_with_new
prc = Proc.new { 'no_return_with_new' }
prc.call
'This is printed'
end
def with_return_and_lambda
prc = lambda { return 'with_return_and_lambda' }
prc.call
'This is printed'
end
p with_return_and_new
p no_return_with_new
p with_return_and_lambda
It seems that the
Proc object is returning not just the value, but the return command too. In general, therefore, it is a bad idea to use an explicit return inside a Proc object defined with Proc.new (if only because the effect will be confusing to anyone with out a good understanding of Ruby peculiarities). This is discussed more here:http://innig.net/software/ruby/closures-in-ruby.rb
API for the Proc object:
http://www.ruby-doc.org/core/classes/Proc.html
See also:
http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/
http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html
# by | 2010/05/09 19:23 | 루비 | 트랙백




