`
hanqingwxf2008
  • 浏览: 50598 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

Ruby学习笔记-Block, Proc and Lambda

    博客分类:
  • ruby
 
阅读更多

1.Block:

  Ruby中的块就是由多行代码组成的一个代码块,通常可以把它认为是一个匿名方法,常用来迭代一个数组或范围(如each, times方法);语法格式如下:

  {            

          //code

  }            

OR

  do          

          //code

  end         

  块变量:当创建一个块时,在两个竖线之间(如: | i |)被称作块变量,作用和一个正常方法的参数一样;如:5.each{| x |  puts x } 

 

2.Block and Array

Block常用来迭代数组,上面也提到过,所以数组中也定义了很多方法接受块参数;常用的有:

  collect:该方法把数组的每一个元素传给块并返回一个新的包括所有元素的数组,原数组的值不变。如果使用collect!方法刚会修改原数组的值;

  each:each方法和collect方法有点类似,会把数组的每个元素的值传递给块,但和collect不同的是,each方法不会创建一个新的包含返回值的数组;没有each!方法;

例:

  a = [1,2,3]

  b = a.collect{|x| x*2}

  puts("-a-")

  puts a

  puts("-b-")

  puts b

  c = a.collect!{|x| x*2}

  puts("-a-")

  puts a

--------------result------------------

  -a-

  1

  3

  -b-

  2

  6

  -a-

  2

  6

       另外,我们怎么迭代一个字符串中的每一个字符?我们首先要做的是用split方法分割字符串,然后再进行迭代;

例:

  a = "hello".each{|x| puts x}

  a = "hello".split (//).each{|x| puts x}

  -------------------result-------------------------------

     hello

  h

  e

  l

  l

  o 

Block在Ruby在有些特别,因为block变不是对象,这与ruby中”一切皆对象”不符合;每一个对象都创建于一个类,我们可以使用class方法来找到某个对象属于哪个类;

例:

  puts( { 1=>2 }.class )                      #Hash

  puts( {|x| puts(x) }.class                  #error

 

3.Proc and Lambda

虽然block默认并不是对象,它们可以”变成”对象。有三种方法用于从block创建对象并把它们分配给变量,格式如下:

  a = Proc.new{ |x| puts x }

  b = lambda{ |x| puts x }

  c = proc{ |x| puts x }

  让我们分别来看一下这三种创建方法;首先,我们可以用Proc.new来创建一个对象并且把一个block作为参数传递给它; 然后,我们可以使用Proc类的call(可以传递一个或多个参数给call方法,这些参数会传递到block里,参数个数取决于block中参数的个数)方法来执行block中的代码;

  我们也可以使用其它两种方法创建一个Proc对象,三种方法都差不多;唯一的区别就是用Proc.new创建的对象不会检查参数的数量,其它两种方法会check;

例:

       a = Proc.new{|x,y,z| x=y*z; puts x}

  a.call(10,20,30,40)                                        #=>600

  b = proc{|x,y,z| x=y*z; puts x}

  b.call(10,20,30,40)                                        #=>error

  c = lambda{|x,y,z| x=y*z; puts x}

  c.call(10,20,30,40)                                        #=>error

 

4.Yield

在Ruby中可以把block当作参数传递给方法,方法里面再使用yield(可以传递参数)关键字调用代码块;

例1:不带参数

       class  Person

              def go()

                     yield

              end

       end

      p = Person.new

  p.go {puts("hello world")}

  Note:我们只是简单的把block放在我们想传递进去的方法的右边,方法接收block,当执行到yield时就会调用block的代码;

例2:带参数

  class  Person

    def go(spead)

      yield(spead)

    end

  end

  p = Person.new

  p.go("ten miles per hour!") {|x| x.capitalize! puts x}

      Note:

  1.在些例中,go方法带有一个参数,spead,并且把这个参数传递到被yield执行的block里面;当调用go方法时,我传递了一个参数(“ten miles per hour!”),当执行到yield语句时,会传递给block参数;

      2.使用yield关键字调用代码块时,如果传入的参数个数少于代码块中定义的参数个数,那么没有传递的参数会自动转为nil。反之,那么最后一个参数为一个数组,该数组包含了剩余的传递参数;

 

5.传递命名的Proc对象

  在Ruby中定义方法时,如果在方法的最后一个形参前增加一个”&”符号,那么Ruby会把这个形参作为一个Proc对象处理(例2);而Proc对象实际上就是一个代码块的封装体,因此在调用方法时需要传递一个block作为参数;

例1:

       def abc( a, b, c )

    a.call            #<= call block a

    b.call            #<= call block b

    c.call            #<= call block c

    yield            #<= yield unnamed block: { puts "four" }

  end

  abc(a, b, c ){ puts "four" }

例2:

  def test( &a )

    a.call             #<= block &d yield

    yield              #<= also block &d

  end

  test{ puts "hello" }                   #法一,传递一个块

      a = proc{puts "world"}

  test(&a)                                    #法二,传递一个Proc对象

 

6.程序优先级

  在传递一个block时,使用{}传递的block比使用do…end的优先级要高;为了避免引起歧义,最好使用大括号将参数括起来;

  1. foo bar do…end:传递到foo方法里面,bar会作为一个参数传递给foo  

  2. foo bar {…}:block会传递到bar里面,返回的值会作为参数传递给方法foo

例:

       def foo( b )

              puts("---in foo---")

              a = 'foo'

              if block_given?

                     puts( "(Block passed to foo)" )

                    yield( a )

              else

                     puts( "(no block passed to foo)" )

              end

              puts( "in foo, arg b = #{b}" )

              return "returned by " << a

  end

 

  def bar

              puts("---in bar---")

              a = 'bar'

              if block_given?

                     puts( "(Block passed to bar)" )

                     yield( a )

              else

                     puts( "(no block passed to bar)" )

              end

              return "returned by " << a

  end

  # ========== Syntax "A" - do..end =======

  puts( '--- (A) do block ---' )

  # calls foo with block

  foo bar do |s| puts( s ) end

 

  # the above is equivalent to

  # foo( bar ) do |s| puts( s ) end

  #    or

  # foo( bar ) { |s| puts(s) }

  puts

  # ========== Syntax "B" - {} =======

  puts( '--- (B) curly braces block ---' )

  # calls bar with block

  foo bar{ |s| puts(s) }

  ------------------------result----------------------------------

  --- (A) do block ---

  ---in bar---

  (no block passed to bar)

  ---in foo---

  (Block passed to foo)

  foo

  in foo, arg b = returned by bar

 

  --- (B) curly braces block ---

  ---in bar---

  (Block passed to bar)

  bar

  ---in foo---

  (no block passed to foo)

  in foo, arg b = returned by bar

  Note:我们可以使用block_given?方法来判定一个方法是否接收了一个block;

分享到:
评论

相关推荐

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

    为了深入理解代码,再次认真学习了一下 Ruby 的闭包,特别是 block,proc 和 lambda 几种用法的异同,这次的周记就和大家分享一下心得。 闭包是 Ruby 相对其它语言特别优势之一,很多语言有闭包,但是唯有 Ruby 把...

    DP-51PROC实验仪原理图 pdf格式

    ### DP-51PROC实验仪原理图解析 #### 核心概述 DP-51PROC实验仪是一款专门用于教学和研究领域的设备,旨在帮助学生理解并掌握微控制器的基础知识及其实现方法。本文将根据提供的PDF格式原理图,对DP-51PROC实验仪...

    ruby笔记1ruby笔记1ruby笔记1

    标题中的"ruby笔记1ruby笔记1ruby笔记1"暗示了这是一份关于Ruby编程语言的学习笔记,可能包含了作者在学习过程中的重点、难点以及心得体验。描述中的内容重复了标题,进一步强调了这是关于Ruby的深入学习记录。标签...

    佳能M-1Proc II线号机驱动

    佳能M-1Proc II线号机是一款专业的标签打印机,主要应用于电气工程、电子设备等领域,用于打印清晰、准确的线缆标识。驱动程序是连接硬件设备与操作系统之间的桥梁,使得操作系统能够识别并控制硬件设备的运行。在这...

    DP-51PROC单片机实验与实践教程(三).doc

    DP-51PROC单片机实验与实践教程(三)

    ruby培训---5天搞定之第1天1

    【Ruby培训---5天搞定之第1天1】 在第一天的Ruby编程基础课程...在接下来的课程中,我们将深入探讨Ruby的更多高级特性,如模块、块、Proc和Lambda,以及Ruby on Rails框架的基础,帮助学员快速掌握完整的Web开发技能。

    开源项目-jasonmoo-lambda_proc.zip

    7. **测试与部署**:由于Lambda Proc允许在Lambda上运行本地进程,因此开发者需要学习如何在本地测试Lambda函数,以及如何打包和部署到AWS Lambda。 8. **安全性**:在Lambda Proc中运行进程可能涉及敏感操作,因此...

    Ruby中使用Block、Proc、lambda实现闭包

    Ruby中的闭包实现有:Block,Proc,Lambada。 首先,我们来看Block。 代码如下: ary = [1,2,3,4] ary.collect! do |a|  a*a end ary.each do |a|  puts a end 这段代码,我们使用了Array对象的block方法,将ary中...

    ruby-2.0.0-p0.tar

    4. **块参数**:Ruby 2.0允许块参数以`&`符号开头,如`&block`,这样可以更方便地将块转换为 Proc 对象,增强了函数式编程的能力。 5. **统一的块调用语法**:在Ruby 2.0中,`yield`和`call`有了统一的调用语法,...

    ORACLE文档--PROC

    Oracle的PROC,全称为Pro*C或ProC Precompiler,是一种集成在Oracle开发工具中的C语言扩展,用于编写高效能的数据库应用。它允许开发者在C或C++代码中嵌入SQL和PL/SQL语句,使得能够直接与Oracle数据库进行交互,...

    coil-20-proc.zip

    总的来说,"coil-20-proc.zip"是一个包含20种物体、每种物体有71个角度变化的图像数据集,它在计算机视觉和机器学习领域中常用于训练和评估物体识别算法,特别是考察算法对物体旋转的鲁棒性。这个数据集的使用不仅...

    linux学习笔记--很经典

    本篇“Linux学习笔记”详细介绍了Linux的基本目录结构及其各自的功能,这对于初学者理解Linux系统的核心概念非常重要。 #### 二、Linux目录结构解析 1. **/(根目录)** - 根目录是Linux文件系统的起点,所有的...

    ruby-language-quickref.zip_About Language

    3. **块、 Proc 和 Lambda**:Ruby支持代码块(blocks),它们是通过`do..end`或花括号`{}`定义的一段代码,可以作为参数传递给方法。Proc和Lambda是代码块的两种可存储形式,它们可以捕获上下文并作为对象进行操作...

    ruby-1.9.3-preview1.zip

    4. **块和 Proc 对象的改进**:在 Ruby 1.9.3 中,块和 Proc 对象可以被赋值给变量,增强了函数式编程的能力。 5. **新的内建类和方法**:引入了更多内建类和方法,如 `Enumerator` 类,以及 `String#encode` 用于...

    Ruby资源ruby-v3.1.1.zip

    2. **Symbol to_proc的优化**:Ruby 3.1对`Symbol#to_proc`进行了优化,提高了使用方法引用作为块时的性能。这在处理集合时特别有用,如`array.map(&:method)`。 3. **Ruby编译器改进**:内部编译器的优化使得代码...

    ruby-doc-bundle

    文档通常包括语言基础(如变量、类、模块、方法等)、控制结构(如if语句、循环、异常处理)、函数式编程特性(如块、Proc和Lambda)以及元编程概念(如类方法、实例方法、动态方法定义等)。 在Ruby的世界里,Gem...

    Ruby学习资料(含参考手册和Programming Ruby)-中文.rar

    这份"Ruby学习资料(含参考手册和Programming Ruby)-中文.rar"压缩包包含了一系列的资源,帮助初学者和进阶者深入理解Ruby语言。 首先,"ruby中文文档(含参考手册和Programming Ruby).chm"是一个综合性的中文参考...

    前端开源库-swint-proc-ops

    为了开始使用 Swint-Proc-Ops,开发者需要熟悉其提供的运算符及其用法,可以通过阅读项目文档、查看示例代码或者研究 `swint-proc-ops-master` 压缩包中的源码来学习。将 Swint-Proc-Ops 集成到现有的 Swint 项目中...

Global site tag (gtag.js) - Google Analytics