原文来自于:
http://railstalk.com/?p=28
Ruby Block先举两个例子,each使用block [1,2,3,4,5].each do | number |puts number end[1,2,3,4,5].each { |number |puts number }可以看出我们使用do...end 或者 {...} 来调用block。 { | number | puts number }这个就是Ruby的blockRuby中的block其实就相当于Javascript中的异步函数,存储了调用函数,直到被调用。其中 | number | 只是异步函数的参数。Ruby 的 block 传递给函数时,使用 █ 这样的形式,在参数前加 & ,则参数被识别为 block。 调用 block 时,需要时 call 。 block.call(...)同时,Ruby block 可以在函数中不声明参数,而只使用yield。如: def call_block_without_argumentyield endcall_block_without_argument { puts "Hello Block" }Ruby ProcProc 对象是一段捆绑在一起的代码,被设置为局部变量,可以在上下文中被调用。例: multiply = Proc.new { | a, b | puts a * b } multiply.call( 3, 4 ) # print out 12同时,可以绑定一系列变量到 Proc ,这样在调用中可以使用这些变量。例: def multiply_with( factor )return Proc.new { | number | number * factor } endmultiply_with 函数将返回一个 Proc 对象,同时包含一个参数。 multiply_with_10 = multiply_with( 10 ) # call multiply_with_10 with a number multiply_with_10.call( 12 ) # return 120 # or you can call in another way multiply_with_10[12] # return 120可以看到 factor 参数在函数中在创建是赋给 Proc,然后就会永久的存在 Proc 中,这样就可以随时调用了。另外,Proc 可以象 Block 一样传递给函数。当然有些不一样的地方。 def print_with_postfix( postfix )return Proc.new { |printing_content| puts "#{printing_content} #{postfix}" }end 然后可以把返回的 Proc 对象象其他函数参数值一样传递给 print_with_postfix 函数。print_with_postfix_bye = print_with_postfix( "bye" ) print_with_postfix_end = print_with_postfix( "end" )def print_content( content, print_style )print_style.call( content ) endprint_content( "Hello world", print_with_postfix_bye ) # print out Hello world bye print_content( "Hello world", print_with_postfix_end ) # print out Hello world endBlock 和 Proc 间的转换使用 & 。 在函数调用时我们使用 &variable 类似的格式来传递参数值,这就把 Block 转换成了 Proc, 这样就可以在函数中使用 call 来调用。同时也可以使用 & 将 Proc 对象转换成 Block。multiply_with_10 = Proc.new { | number | puts number * 10 } [1,2,3,4].each( μltiply_with_10 ) # 10 # 20 # 30 # 40因为在 each 函数中接收 block 作为参数值。而这里我们使用了一个 Proc,就需要加上 & 来把 Proc 转换为 Block。Lambda lambda 是创建 Proc 的函数 multiply_lambda_proc = lambda { | x, y | x * y } # and we can call as a normal Proc multiply_lambda_proc.call( 3, 4 ) # return 12但 lambda 和 proc 有两个不同点: lambda 对参数做检查,而 proc 不检查。例:multiply_lambda_proc = lambda { | x, y | x * y } multiply_proc = Proc.new { | x, y | x * y }multiply_lambda_proc.call( 3, 4, 5 ) # ArgumentError: wrong number of arguments (3 for 2) multiply_proc( 3, 4, 5 ) # return 12 as normal# This last command's error shows that Proc auto assigns missing argument with nil multiply_proc( 3 ) # TypeError: nil can't be coerced into Fixnumlambda 返回到调用者的函数,而 proc 返回到内部的函数。def return_from_procruby_proc = Proc.new { return "return from a Proc" }ruby_proc.callreturn "The function will NOT reach here because a Proc containing a return statement has been called" enddef return_from_lambdaruby_lambda = lambda { return "return from lambda" }ruby_lambda.callreturn "The function will reach here" endputs return_from_proc # display return from proc puts return_from_lambda # display The function will reach here在这个例子中,可以看到 proc 包含的一个 return 语句被调用,将会返回整个函数,而lambda