• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Ruby中的block、proc、lambda区别总结

    在规则引擎中,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的情况,他们的行为是一致的,但是主要在两个地方有明显差异:

    1.1 参数检查

    还是例子说话 Example 3:

    复制代码 代码如下:

    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)

    输出

    复制代码 代码如下:

       》a is 100 b is nil
       》a is 100
       》ArgumentError: wrong number of arguments (1 for 2)
          …

    可见,proc 不会对参数进行个数匹配检查,而 lambda 会,如果不匹配还会报异常,所以安全起见,建议优先用 lambda。

    1.2 返回上层

    还是例子说话 Example 4:

    复制代码 代码如下:

     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

    输出

    复制代码 代码如下:

       》return from foo from inside proc
       》return from lambda
       》return from bar

    可见,proc 中,return 相当于执行了闭包环境里的 return,而 lambda 只是返回call 闭包所在环境。

    总结:闭包是 Ruby 的强大特性,它的几种表达方式block,proc 和 lambda有细微差别,要用好它需要对其深入理解。

    您可能感兴趣的文章:
    • 实例讲解C++编程中lambda表达式的使用
    • 结合C++11新特性来学习C++中lambda表达式的用法
    • C++中的Lambda表达式详解
    • C++实现的一个可以写递归lambda的Y函数
    • Ruby中使用Block、Proc、lambda实现闭包
    • python中lambda函数 list comprehension 和 zip函数使用指南
    • Python中的特殊语法:filter、map、reduce、lambda介绍
    • Ruby中proc和lambda的两个区别
    • 浅析C++11新特性的Lambda表达式
    上一篇:Ruby中的p和puts的使用区别浅析
    下一篇:Ruby的运算符和语句优先级介绍
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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