zoukankan      html  css  js  c++  java
  • Ruby Block和迭代器

    我们来简单地描述Ruby的一个独特特性。Block,一种可以和方法调用相关联的代码块,几乎就像参数一样。这是一个不可思议的功能强大的特性。

    可以用Block实现回调(但它比Java的匿名内部(anonymous inner)类更简单),传递一组代码(但它远比c的函数指针灵活),以及实现迭代器。

    Block只是在花括号或者do...end之间的一组代码。

    {puts "Hello"}                          #this is a block

    do                                           ### 

      club.enroll(person)                       #and so is this

      person.socialize                           #

    end                                          ###

    为什么有两种分界符?部分原因是有人觉得有时候用一种分界符比另外一种感觉更自然。另外一部分原因是它们有不同的优先级:花括号比do/end绑定的更紧密些。我们尝试遵循正在成为Ruby标准的一个约定俗成,单行block用花括号,多行block用do/end。

    一旦创建了block,就可以与方法的调用相关联。把block的开始放在含有方法调用的源码行的结尾处,就可以实现关联。比如,在下面的代码中,含有puts "Hi" 的block与greet方法的调用相关联。

    greet {puts "Hi"}

    如果方法有参数,它们出现在block之前。

    verbose_greet("Dave","loyal customer"){puts "Hi"}

    然后使用Ruby的yield语句,方法可以一次或多次地调用(invoke)相关联的block。可以把yield想象成比如方法调用,它调用含有yield语句的方法所关联的block。

    下面的例子显示了如何使用yield语句。定义了一个方法,它会调用yield两次。然后调用这个方法,把block放在同一行,在方法调用之后(并在方法的所有参数之后)。

    def call_block

      puts "Start of method"

      yield

      yield

      puts "End of method"

    end

    call_block{puts "In the block"}

    输出结果:

      Strat of method

      In the block

      In the block

      End of method

    可以提供参数给yield的调用;参数会传递到block中。在block中,竖线(|)之间给出参数名来接受这些来自yield的参数。

      def call_block

        yield("Hello",99)

      end

      call_block {|str,num| ...}

    在Ruby库中大量使用了block来实现迭代器;迭代器是从某种收集(collection)如数组中连续返回元素的方法。

    animals = %w(ant bee cat dog elk)    #创建一个数组

    animals.each{|animal| puts animal}    #迭代它的内容

    输出结果:

    ant

    bee

    cat

    dog

    elk

    让我们看一下如何实现应用在前面例子中的Array类中的each迭代器。each迭代器循环处理数组中的元素,对每个元素调用yield。在伪码中,它可能写成:

    #在Array类中......

    def each

      for each element                  #<--无效的Ruby语句

        yield(element)

      end

    end

    许多内建于c和java等语言的循环结构在Ruby中只是方法调用,这些方法会零次或多次地调用相关联的block。

    ['cat','dog','horse'].each{|name| print name," "}

    5.times {print "*"}

    3.upto(6){|i| print i}

    ('a'..'e').each{|char| print char}

    输出结果:

    cat dog horse *****3456abcde

    上面的代码要求对象5 五次调用block;然后要求对象3调用一个block,并传入一个连续的值,直到这个值到达6为止。最后对a到e的字符区间(range),使用each方法调用block。

  • 相关阅读:
    关于binary log那些事
    Ubuntu常用软件安装与使用
    Ubuntu 12.04系统优化清理
    Ubuntu 12.04开机自动挂载Windows分区
    wubi安装Ubuntu后扩充Ubuntu系统空间
    sudo找不到命令:修改sudo的PATH路径
    JS 获取触发事件的对象
    NOIP 2002
    NOIP 2011 聪明的质监员
    NOIP 2011 计算系数
  • 原文地址:https://www.cnblogs.com/timsheng/p/2584601.html
Copyright © 2011-2022 走看看