源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Ruby中的block、proc、lambda区别总结

  • 时间:2021-12-14 16:14 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Ruby中的block、proc、lambda区别总结
在规则引擎中,Ruby 的闭包使用特别频繁,而且有 block,Proc和 lambda 等后几种形式的用法,很让人困惑。为了深入理解代码,再次认真学习了一下 Ruby 的闭包,特别是 block,proc 和 lambda 几种用法的异同,这次的周记就和大家分享一下心得。 闭包是 Ruby 相对其它语言特别优势之一,很多语言有闭包,但是唯有 Ruby 把闭包的优势发挥得淋漓尽致。Ruby 的哲学之一:同一个问题现实中有多种解决方法,所以 Ruby 中也有多种解法,所以闭包的使用也有多种方法。 先看一个代码的例子: Example 1:
[u]复制代码[/u] 代码如下:
def foo1   yield end def foo2(&b)   b.call if b end foo1 { puts "foo1 in block" } foo2 { puts "foo2 in block" } proc = Proc.new { puts "foo in proc" } foo1(&proc) foo2(&proc) lambda_proc = lambda { puts "foo in lambda" } foo1(&lambda_proc) foo2(&lambda_proc)
输出:
[u]复制代码[/u] 代码如下:
》foo1 in block 》foo2 in block 》foo in proc 》foo in proc 》foo in lambda 》foo in lambda
大家是不是有些困惑,首先是方法 foo1 和 foo2 都能接收闭包,它们这两种写法有什么区别,然后是作为参数的三种闭包 block,proc和 lambda有什么区别。 [b]1. yield 和 block call 的区别[/b] yield 和 block call 两种都能实现运行闭包,从实际运行效果来说,区别不大。其区别主要在于: [b]1.1 闭包的传递和保存[/b] 因为闭包已经传递到参数里,所以可以继续传递或保存起来,例如: Exampl 2:
[u]复制代码[/u] 代码如下:
 class A       def foo1(&b)          @proc = b       end       def foo2           @proc.call if @proc       end    end     a = A.new     a.foo1 { puts "proc from foo1" }     a.foo2
[b]1.2 性能[/b] yield不是方法调用,而是 Ruby 的关键字,yield 要比 block call 比快 1 倍左右。 [b]2. block 和 proc, lambda 的区别[/b] 很简单直接,引入 proc 和 lambda 就是为了复用,避免重复定义,例如在 example 1 中,使用 proc 变量存储闭包,避免重复定义两个 block 。 [b]3. proc 和 lambda 的区别[/b] 这大概是最让人困惑的地方,从 Example 1 的行为上看,他们的效果是一致的,为什么要用两种不同的表达方式。
[u]复制代码[/u] 代码如下:
 proc = Proc.new { puts "foo in proc" }    lambda_proc = lambda { puts "foo in lambda" }
确实,对于简单的情况,比如 Example 1的情况,他们的行为是一致的,但是主要在两个地方有明显差异: [b]1.1 参数检查[/b] 还是例子说话 Example 3:
[u]复制代码[/u] 代码如下:
def foo       x = 100       yield x    end    proc = Proc.new { |a, b| puts "a is #{a.inspect} b is #{b.inspect}" }    foo(&proc)    lambda_proc1 = lambda { |a| puts "a is #{a.inspect}" }    foo(&lambda_proc1)    lambda_proc2 = lambda { |a, b| puts "a is #{a.inspect} b is #{b.inspect}" }    foo(&lambda_proc2)
输出
[u]复制代码[/u] 代码如下:
   》a is 100 b is nil    》a is 100    》ArgumentError: wrong number of arguments (1 for 2)       …
可见,proc 不会对参数进行个数匹配检查,而 lambda 会,如果不匹配还会报异常,所以安全起见,建议优先用 lambda。 [b]1.2 返回上层[/b] 还是例子说话 Example 4:
[u]复制代码[/u] 代码如下:
 def foo      f = Proc.new { return "return from foo from inside proc" }      f.call # control leaves foo here      return "return from foo"    end    def bar      f = lambda { return "return from lambda" }      puts f.call # control does not leave bar here      return "return from bar"    end    puts foo    puts bar
输出
[u]复制代码[/u] 代码如下:
   》return from foo from inside proc    》return from lambda    》return from bar
可见,proc 中,return 相当于执行了闭包环境里的 return,而 lambda 只是返回call 闭包所在环境。 总结:闭包是 Ruby 的强大特性,它的几种表达方式block,proc 和 lambda有细微差别,要用好它需要对其深入理解。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部