首页 > 学院 > 开发设计 > 正文

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

2019-10-26 19:25:21
字体:
来源:转载
供稿:网友

在规则引擎中,Ruby 的闭包使用特别频繁,而且有 block,Proc和 lambda 等后几种形式的用法,很让人困惑。为了深入理解代码,再次认真学习了一下 Ruby 的闭包,特别是 block,proc 和 lambda 几种用法的异同,这次的周记就和大家分享一下心得。

闭包是 Ruby 相对其它语言特别优势之一,很多语言有闭包,但是唯有 Ruby 把闭包的优势发挥得淋漓尽致。Ruby 的哲学之一:同一个问题现实中有多种解决方法,所以 Ruby 中也有多种解法,所以闭包的使用也有多种方法。

先看一个代码的例子:

Example 1:
代码如下:
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)

输出:
代码如下:
》foo1 in block
》foo2 in block
》foo in proc
》foo in proc
》foo in lambda
》foo in lambda

大家是不是有些困惑,首先是方法 foo1 和 foo2 都能接收闭包,它们这两种写法有什么区别,然后是作为参数的三种闭包 block,proc和 lambda有什么区别。

1. yield 和 block call 的区别

yield 和 block call 两种都能实现运行闭包,从实际运行效果来说,区别不大。其区别主要在于:

1.1 闭包的传递和保存

因为闭包已经传递到参数里,所以可以继续传递或保存起来,例如:

Exampl 2:
代码如下:
 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

1.2 性能

yield不是方法调用,而是 Ruby 的关键字,yield 要比 block call 比快 1 倍左右。

2. block 和 proc, lambda 的区别

很简单直接,引入 proc 和 lambda 就是为了复用,避免重复定义,例如在 example 1 中,使用 proc 变量存储闭包,避免重复定义两个 block 。

3. proc 和 lambda 的区别

这大概是最让人困惑的地方,从 Example 1 的行为上看,他们的效果是一致的,为什么要用两种不同的表达方式。
代码如下:
 proc = Proc.new { puts "foo in proc" }
   lambda_proc = lambda { puts "foo in lambda" }

确实,对于简单的情况,比如 Example 1的情况,他们的行为是一致的,但是主要在两个地方有明显差异:

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表