zoukankan      html  css  js  c++  java
  • iterator ruby introduce

    http://ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html

    C:\Users\Administrator>irb
    irb(main):001:0> def a(name)
    irb(main):002:1> yield
    irb(main):003:1> puts "hello"
    irb(main):004:1> yield
    irb(main):005:1> end
    => nil
    irb(main):006:0> a("1")
    LocalJumpError: no block given (yield)
            from (irb):2:in `a'
            from (irb):6
            from C:/Ruby192/bin/irb:12:in `<main>'
    irb(main):007:0> a("dd") do
    irb(main):008:1* puts "z"
    irb(main):009:1> end
    z
    hello
    z
    => nil
    irb(main):010:0> aa=a("dd") do
    irb(main):011:1* puts "z"
    irb(main):012:1> end
    z
    hello
    z
    => nil
    irb(main):013:0> aa=a("dd") do
    irb(main):014:1* "z"
    irb(main):015:1> end
    hello
    => "z"
    irb(main):016:0>

    Ruby代码块是用大括号或者do...end括起来的一系列代码。

    1. { puts "Hello" }

    Ruby代码块贯穿在实现迭代器的Ruby库中,迭代器就是一种方法,用来连续返回某种集合的元素,比如一个数组。

    块的真正的作用是当你创建了一个块之后,你就可以将它与函数联系在一起。你可以在调节器用函数的那一行代码之后加入一个块。

    e88f9031ab1725ac5fdf0e42[1]

    http://developer.51cto.com/art/200912/170500.htm

    &block

    使用

    http://blog.codahale.com/2005/11/24/a-ruby-howto-writing-a-method-that-uses-code-blocks/

    TidyRead

    Style:





    Background
    Foreground
    Link Color
    Link Visited

      Size:




      Width:



    More

    Open Mode
    Overlay Original
    Replace Original


    Font
    Arial
    Tahoma
    Verdana
    Georgia
    Segoe
    Times
    Book
    Comic
    Courier
    Trebuchet
    Palatino
    Lucida
    Text Align
    Left
    Justify
    Text Dir
    Left to Right
    Right to Left
    Disable TidyRead
    Save Settings
    Print
    Close

    《Ruby》Ruby代码块和迭代器

    推荐给好友收藏到IE收藏夹收藏到QQ书签收藏到百度收藏到Google

    作者:追梦  来源:http://www.itrenjia.org   日期:2010-07-25 22:54:38  (共有0条评论)我要评论

    第五章代码块和迭代器
    &sect;5.1 代码块(Block)
    &sect;5.1.1什么是代码块
    在Ruby中在在大括号之间的代码或放在do/end之间的代码是一个代码块。代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上

    第五章代码块和迭代器

    §5.1 代码块(Block)

    §5.1.1什么是代码块

    在 Ruby中在在大括号之间的代码或放在do/end之间的代码是一个代码块。代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上。代码块的内容并不会被马上执行,当执行到被调用的方法时,解释器的运行时环境会记住代码块出现的现场,然后执行被调用的方法。

    [1,2,3,4,5].each { |i|

        puts i

    }

    [1,2,3,4,5].each do |i|

        puts i

    end

    一般的使用习惯是:(to-do 具体解释)

    l 当关心边际(side effect)效应时使用 do/end。

    l 当关心返回结果应时使用大括号。

    §5.1.2代码块与对象

    代码块并不是对象,但可以方便的转化为Proc类的对象。有三种转化的方法:

    l 将一个代码块传递给最后一个参数以&开始的方法。

    def meth1(p1, p2, &block)

         puts block.inspect

         puts block.call

    end

    meth1(1, 2) { "This is a block" }

    l 使用Proc.new方法,后边的参数为一个代码块:

    block = Proc.new { "a block" }

    l 调用Kernel.lambda方法:

           block = lambda { "a block" }

    前两种方法是等价的,而第三种方法,用 lambda 生成的 Proc 对象和用 Proc.new 生成的 Proc 对象之间是有差别的。这是一个微妙的差别,这个差别与 return 关键字相关。lambda 中的 return 从 lambda 返回。而 Proc 中的 return 从外围方法返回。

    可以看以下两个例子:

    def test_proc

        p = Proc.new { return 1 }

        p.call

        puts "Never come here"

    end

    test_proc     #=> 1

    执行后"Never come here"不会被输出,执行p.call相当于在test_proc方法内执行了return语句。

    def test_lambda

        p = lambda { return 1 }

        result = p.call

        puts "The value is: #{result}"

    end

    test_lambda

    执行后的结果为:

    The value is: 1

    可见使用lambda生成的Proc对象执行call方法调用时,return表示从lambda包围得块内返回。

    在一个代码块中执行next语句会导致代码块返回。返回值就是next语句后带的参数。如果next后没有参数,那么返回值为nil。

    def meth2

           result = yield

           "The block result is #{result}"

    end

    puts meth2 { next 9 }

    pr = Proc.new { next 100 }

    puts pr.call

    pr = lambda { next }

    puts pr.call

    执行结果为:

    The block result is 9

    100

    nil

    §5.2 迭代器(Iterator)

    §5.2.1什么是迭代器

    简单的讲,一个迭代器就是一个能接受代码块的方法。当初为了进行迭代操作而设置了带块方法,所以现在它仍然常常被称作迭带器。

    [1,2,3,4,5].each { |i|

            puts i

    }

    上述代码中,each方法反复调用代码块,我们称each方法为一个迭代器。

    迭代器(Iterator)即指调用带块方法。实际上,在早期版本的 Ruby 中,使用代码块的方法被称为迭代器,因为它们就是被设计来实现循环迭代的。但是在Ruby发展过程中,代码块的用途在后来已经得到了很大的增强,从最初的循环抽象到任何事情。可以将那些进行迭代操作的方法叫做迭代器,但如果将所有带块方法的调用过程都看作迭带器的话,并不合适而且概念上会引起混乱

    §5.2.2使用迭代器

    #一个使用迭代器的简单例子,数组中每一个元素作为参数执行其后的代码块

    ['This', 'is', 'a', 'dog'].each do |entry|

           print entry, ' '

    end

    执行结果为:

        This is a dog

        #另一个使用迭代器的例子,代码块可以访问其外的数据

    factorial = 1

    1.upto(10) do |i|

            factorial*= i

    end

    puts factorial

    执行结果为:

        3628800

    #代码块的返回值可以被调用者使用

    b = [1, 2, 3, 4, 5].map do |entry|

        entry * entry

    end

    print b.inspect

    执行结果为:

        [1, 4, 9, 16, 25]

    #代码块也可以使用一个以上的参数

    result = (0..100).inject(0) do |sum, i|

        sum + i

    end

    print result

    执行结果为:

    5050

    §5.2.3 yield

    在方法中可以使用yield来执行代码块的内容,就好像传入的代码块是这个方法的一部分一样。每当碰到一个yield调用,代码块的内容就会被执行一次。当代码块执行结束后,程序会回到yield的那一行继续向下执行。

    def twoTimes

            yield

            yield

    end

    twoTimes { puts "Hello World!" }

    执行结果为:

    Hello World!

    Hello World!

    你可以使用yield操作传参数给一个代码块,并且从代码块取回返回值。

    def fibonacii(max)

           f1, f2 = 1, 1

           while f1 <= max

               yield f1

               f1, f2 = f2, f1+f2

           end

    end

    fibonacii(1000) { |f| print f, " " }

    执行结果为:

        1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

    在这个例子中,yield接收一个参数,这个参数将会在执行的时候传递给指定的代码块。在代码块中,接收的参数使用两个竖线括起来放在代码块的头部。yield操作也可以有返回值,yield操作的返回值就是代码块中最后一个表达式的值。

    §5.2.4 编写自己的迭代器

    def factorial(count, &block)

            value = 1

            1.upto(count) do |i|

                value = value * i

                block.call(i, value)

            end

    end

    factorial(5) do |i, sum|

            puts "factorial(#{i}) = #{sum}"

    end

    执行结果为:

    factorial(1) = 1

    factorial(2) = 2

    factorial(3) = 6

    factorial(4) = 24

    factorial(5) = 120

    也可以将传入的代码块保存以供以后使用:

    class Mathematics

            def initialize(&block)

               @block = block

            end

            def factorial(max)

                value = 1

                1.upto(max) do |i|

                   value = value * i

                   @block.call(value)

                end

            end

    end

    the_value = Mathematics.new do |count|

            puts "Current value is #{count}"

    end

    the_value.factorial(5)

    执行结果为:

    Current value is 1

    Current value is 2

    Current value is 6

    Current value is 24

    Current value is 120

    关键词:Ruby代码块和迭代器

    下一篇《Ruby》Ruby基本类型

    您看到此新闻时的感受是:
    • 支持
      支持
    • 高兴
      高兴
    • 震惊
      震惊
    • 愤怒
      愤怒
    • 无奈
      无奈
    • 谎言
      谎言
    • 枪稿
      枪稿
    • 不解
      不解
    • 搞笑
      搞笑
    • 无聊
      无聊
    • 标题党
      标题党
    相关文章
    用户评论

      TidyReadClose TidyRead

      http://www.itxuexi.com/tech/script/ruby/85561252680952.html

      TidyRead

      Style:





      Background
      Foreground
      Link Color
      Link Visited

        Size:




        Width:



      More

      Open Mode
      Overlay Original
      Replace Original


      Font
      Arial
      Tahoma
      Verdana
      Georgia
      Segoe
      Times
      Book
      Comic
      Courier
      Trebuchet
      Palatino
      Lucida
      Text Align
      Left
      Justify
      Text Dir
      Left to Right
      Right to Left
      Disable TidyRead
      Save Settings
      Print
      Close

      Ruby入门介绍

      2009-09-11 22:55:52 来源:脚本之家(www.jb51.net) 【 评论:0 条

      -

      一、方法
      Ruby 的方法定义允许为参数设置默认值,不过在带有默认值的参数后面不能出现不带有默认值的参数(允许 * 和 &),也就是说下面的方法定义是不被允许的,解释时会出现 parse error。 还有一点与 C# 不同的是,方法定义不能出现在方法调用的后面。

      # parse error def Display(args1="proshea", args2) end # 允许 def Display(args1="proshea", *args2) end # 允许 def Display(args1="proshea", &args) end Show() # 出现在 Show 调用之后是错误的 def Show end

      Ruby 也支持 C# params 这样的参数功能, 只是 Ruby 用 * 标识罢了。

      def Display(*args) print %Q~#{args.join("-")}~ end # proshea-32-WinForm Display("proshea", 32, "WinForm")

      同样的, Ruby 也有类似于 C# delegate 的应用,只是更简单,直接用 & 来表示,并且 Ruby 用一个称为 yield 的关键字来知会解释器执行传入的代码块或者说 Proc object(过程对象?)。

      1def Display(&block) 2 if block_given? 3 yield(block) 4 else 5 print %Q~没有传入过程对象~ 6 end 7end 8 9def Show() 10 print %Q~Show 方法调用~ 11end 12 13# 没有传入过程对象 14Display() 15# 在 Display 内部调用 Show 方法 16# 注意起始大括号仍然只能和方法名在同一行 17Display(){ 18 Show() 19}

      block_given? 是被定义在内部模块 Kernel 当中的方法,用以表明是否传入了 Proc object。之后,Ruby 用 yield 通知解释器执行传入的 Proc。过程对象也可以带有参数,不同于普通方法的是过程对象的参数是位于一组 | | 之中。可以使用 Proc object 的 call 方法来调用带参数的过程对象。

      1class Employee 2 def initialize(username, age, &block) 3 @username, @age, @block = username, age, block 4 end 5 6 def Display(txt) 7 # 虽然 @block 是个实例变量,但在此处一定要加上大括号 8 print "#{@block.call(txt)}: #@username-#@age" 9 end 10end 11 12emp = Employee.new("proshea", 32){ 13 |txt| 14 txt 15} 16emp.Display("context")

      1

      -

      1 2 3 4 5 下一页

      您看完这篇文章的心情是: <已有0人发表看法>

      0

      0

      0

      0

      0

      0

      0

      0








      吃惊
      欠揍
      支持
      很棒
      一般
      搞笑
      扯淡
      不解

      收藏到网摘:QQ书签 雅虎收藏夹 百度收藏 Google书签 新浪ViVi 天极网摘 Del.icio.us digg reddit 收藏本页

      Tags:Ruby 入门
    • 上一篇:什么是ruby和Ruby概述
    • 下一篇:Ruby入门点滴-Ruby的安装
    • 相关文章列表

      评论 (0)

      没有评论

      推荐文章

      -

      TidyReadClose TidyRead

      注册 登录

      Ruby

      统计

      发布时间
      2008-27-09 04:06

      浏览数量
      811

      回复数量
      1

      收藏数量
      0

      最新讨论话题

      谁收藏了此话题

      几个高级特性的理解

      shitou 2 年之前

      面向对象的思想在ruby中表现的淋漓尽致,几个特性也是比较难以理解的,这里做个小总结:

      1. super

      先看例子吧:

      class Father
          def hello
              p 'hello, i am dad'
          end
      end
      
      
      class Child < Father
          def hello
              p 'hello, i am son'
              super
      
      
          end
      
      
      end
      
      
      Father.new.hello
      #hello, i am dad
      Child.new.hello
      #hello, i am dad
      #hello, i am son

      ruby类中方法查找路径为:类实例先查找本类中是否定义了该方法, 然后查找该类中是否include了其他module,该mudule中是否包含了改方法, 然后查找该类的父类中是否有改方法, 然后是父类中是否include了其他module,改mudole中是否包含了其他方法。
      在查找的整个过程中如果查找到将会立刻执行并停止向上一级的查找

      super可以理解为,按照上面的查找路径再向上一级进行查找, 如果有,就在该处(调用super的逻辑片段中)再执行一遍改匹配该方法名的方法,如果整个查找过程都没有匹配到,将会抛出异常 NoMethodError,所以上面的例子就不难理解了, 要注意的是super不是只查找自己父类中的同名方法, 包括module的

      另外super也接受参数:
      super, 及没有加任何参数时(裸词), 是默认自动向前传递所有该方法所获得的参数
      super(), 不向上一级传递任何参数
      super(a,b,c), 传递指定的参数

      2. <<

      <<用来批量定义类或者模块的方法(注意不是实例方法)

      下面两段代码的效果是一样

      class As
          def As.hello
              #do something
      
      
          end
      end
      
      
      class As
          class << self
              def hello
                   #do something
              end
          end
      end

      同理下面两段代码的效果是一样的

      module TimeFormat
          def self.show_time
              #do something
          end
      end
      
      
      module TimeFormat
          class << self
              def show_time
                  #do something
              end
          end
      end

      3. yield和block

      block在ruby是独有的特性, 其中yeild的使用更是灵活

      下面是内置类File :pen的源码

      def File.open(name, mode = "r")
          f = os_file_open(name, mode)
          if block_given?
              begin
                  yield f
              ensure
                  f.close
              end
              return nil
          else
              return f
          end
      end

      这个方法非常简洁明了,block_given?判断是否传递了代码块,有的话就把文件句柄传给代码块进行操作,这个地方就是

      yield f

      我觉得可以这样理解yield的行为:把yield后面的参数传递给后面的代码块作为参数。
      yield的作用可以这样理解:拿学生举个例子,每个学生交的学费是一样的,所以处理交学费的流程就放在方法中,但是每个学生的要花费的生活费不一样,要考虑很多的因素,所以把特殊的因素放在代码块中操作,这样就可以即统一又有区别的计算出总的花费。

      另一个例子

      def  c(v, &block)
          return v unless v.is_a? Array
          v.each &block if block_given?
      
      
      end
      c([1,2,3]) { |x| p x + 1 }    #2, 3, 4
      
      
      def c(v)
          return v unless v.is_a? Array
          v.each { |x| yield x } if block_given?
      end
      c([1,2,3]) { |x| p x + 1 }    #2, 3, 4

      [ 本帖最后由 shitou 于 2008-9-27 12:08 编辑 ]

      回到顶部 | 回复主题

      理解了上面的,当你想往rails的model中添加自己的类方法或者重写内置方法时就可以

      class << ActiveRecord::Base
          def  your_action
              #do something
          end
      end

      [ 本帖最后由 shitou 于 2008-9-27 12:17 编辑 ]

      发表讨论

      在回复之前你需要先进行登录

      账户或邮箱

      密码

      记住我的登录状态 (忘记密码)

      返回首页 | Ruby | 回到顶部

      © 2008-2011 Kohana 中文

      Rendered in 0.76981秒. Powered by Alpaca

    查看全文
  • 相关阅读:
    iOS学习,需要懂的一些基础
    学习RAC小记-适合给新手看的RAC用法总结(转)
    UITableView进阶,cell刷新,界面返回 保持所选cell
    冒泡排序
    ArrayList 实现随机点名
    ArrayList的使用
    java中一维数组的定义和遍历
    java 中二维数组的定义和遍历
    Java 引用数据类型
    java 中自定义类的概述
  • 原文地址:https://www.cnblogs.com/lexus/p/1935119.html
  • Copyright © 2011-2022 走看看