Ruby 中的 block、proc、lambda

130 篇文章 0 订阅


原文来自于:
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的block

Ruby中的block其实就相当于Javascript中的异步函数,存储了调用函数,直到被调用。

其中 | number | 只是异步函数的参数。

Ruby 的 block 传递给函数时,使用 █ 这样的形式,在参数前加 & ,则参数被识别为 block。 调用 block 时,需要时 call 。
block.call(...)

同时,Ruby block 可以在函数中不声明参数,而只使用yield。如:
def call_block_without_argument
     yield        
end

call_block_without_argument { puts "Hello Block" }

Ruby Proc

Proc 对象是一段捆绑在一起的代码,被设置为局部变量,可以在上下文中被调用。例:
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 }
end

multiply_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 )
end
 
print_content( "Hello world", print_with_postfix_bye ) # print out Hello world bye
print_content( "Hello world", print_with_postfix_end ) # print out Hello world end

Block 和 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 Fixnum

lambda 返回到调用者的函数,而 proc 返回到内部的函数。

def return_from_proc
      ruby_proc = Proc.new { return "return from a Proc" }
      ruby_proc.call
      return "The function will NOT reach here because a Proc containing a return statement has been called"
end

def return_from_lambda
      ruby_lambda = lambda { return "return from lambda" }
      ruby_lambda.call
      return "The function will reach here"
end

puts return_from_proc # display return from proc
puts return_from_lambda # display The function will reach here

在这个例子中,可以看到 proc 包含的一个 return 语句被调用,将会返回整个函数,而lambda 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值