分享

ruby系列教材(6):Blocks and Iterator

 漂在北方的狼 2006-12-06

Blocks:代码段,使用起来就像参数(parameters)一样 

先来说说Blocks的表现形式:

1.{puts "hi"}      #用{}表示Blocks,请在只有一行的时候使用{}

2.

do

  puts "hi"

end                    #用do...end表示Blocks,多行的时候使用do...end...

 

说明:实际上,{}和do...end是一样的,可以使用在多行,但是ruby的标准,规定,{}用于只有一行的情况,而do...end使用在有多行的情况

 

 

使用Blocks:

Blocks使用起来和parameters一样,可以这样用:

1.greet { puts "Hi" }                                                              #没有parameters的情况

2.verbose_greet("Dave", "loyal customer") { puts "Hi" }       #有参数的情况

那Blocks是怎么样被方法所调用的?方法通过一个statement---yield来调用,例如:

def call_block

puts "Start of method"

  yield                                                    #yield部分被block代替

  yield                                                    #1个method可以有多个yield

puts "End of method"

end

call_block { puts "In the block" }

 

produces:

Start of method

In the block

In the block

End of method

 

 

yield:

yield是一个statement,而不是method

yield可以带parameters(此说法来源于《programming ruby》),比如:yield("hi",123),一个更加具体的例子:

 

#本代码模拟times

def mytimes p
  i=0
  while i <= p
    yield(i)
    i = i+1
  end
end

mytimes(3){|i| p i}    #p 是一个类似于print,puts的打印的method

 

结果:

0
1
2
3

上面的代码说明:yield的parameter,传递给了block里面对应的variable,block在利用variable进行有关操作。也许这一切有点难以理解,你可以想象block就是一个方法,它可以接受parameters,而|i|就是对参数的声明,yield会把自己的parameters传递到block里面。

*假如我们在方法里面放入了yield,但是在调用的时候没有使用block会是什么样的?允许吗?

例如:

def mytimes p
  i=0
  while i <= p
    yield(i)
    i = i+1
  end
end

mytimes(3)        #不使用block

结果:

4:in `mytimes‘: no block given (LocalJumpError)
   from a.rb:9

 

所以,在使用了yields的情况下面,必须使用blocks

另外一个问题出来了,假如是yield带有参数,block却没有对应的参数,会怎么样?

例如:

def mytimes p
  i=0
  while i <= p
    yield(i)
    i = i+1
  end
end

mytimes(3){}   #无参数

结果:

  

#一个空白行,可以运行

 

再看:

def mytimes p
  i=0
  while i <= p
    yield(i)
    i = i+1
  end
end

mytimes(3){|a,b| p a}    #带有2个参数

 

结果:

0
1
2
3

继续看:

def mytimes p
  i=0
  while i <= p
    yield(i)
    i = i+1
  end
end

mytimes(3){|a,b| p b}     #这次打印 b

 

结果:

nil
nil
nil
nil

 

我想读者应该知道了吧,总结一下:出现yield就必须使用block,但是block和yield的parameters不一定要匹配,blocks中variable的初值是nil

 

 

 

iterators:(迭代器)

iterators是一种method,object of collections 可以使用它,collections在Arrays and Hashes里面已经提到,最常见的就是Arrays and Hashes了,我们可以形象的认为他们的关系是:collection.literator,举例:

animals = %w( ant bee cat dog elk )        # create an array

animals.each {|animal| puts animal }        # iterate over the contents

each就是一个iterator,它是class Array 的一个方法

 

下面举例来说说各种iterators:

[ ‘cat‘, ‘dog‘, ‘horse‘ ].each {|name| print name, " " }          #这里有点要注意的就是,print后面可以接多个parameters,同样的p,puts都可以

 

5.times { print "*" }

5.times {|i| p i}                         # Fixnum 类的 iterators:times

 

3.upto(6) {|i| print i }               # Fixnum 类的 iteratros:upto

 

(‘a‘..‘e‘).each {|char| print char }   # Range 类的 iterators:each,Range也是一个collections,each在所有collections里都有定义

 

Range 类:表现形式,(1..9),(‘a‘..‘k‘)

 

符号 意义
( )

Ranges

[ ] Arrays
{} Hashes

%w()

%w[]

%w{}

Arrays

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多