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








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

    收藏到网摘:

    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

    你可能感兴趣的:(iterator)