Ruby-迭代器和代码块
Varsion
1
loop {puts "loop forever" }

loop是一个迭代器,是一种方法。他在调用的语法上附加了一个条件:需要额外提供一个代码块。

loop方法访问了在代码块中的代码:方法可以调用执行该代码块。为了在迭代器中实现它,可以使用关键字yield。代码块(由调用代码提供)和yield(从方法内部调用)一同作为调用的主要条件。

迭代

loop的任务是为了把控制教改代码块,然后不断的循环。

1
2
3
4
5
6
7
8
9
def my_loop
while true
yield
end
end
# 或者更简短的方式
def my_loop
yield while true
end

然后就可以像调用loop一样使用my_loop

提供一个代码块给my_loop方法,就能交出控制权(yield)。当方法的控制权交给代码块,其中的代码运行完毕之后,控制权会立刻返回到方法中调用yield的的地方。

解析方法调用

Ruby中的每个方法调用都遵循一下的语法:

  • 接收者对象或者变量(如果缺少则默认为self
  • 点(假如有明确的接收者则为必要条件,不允许其他情况
  • 方法名(必要
  • 参数列表(可选,默认为()
  • 代码块(可选,没有默认

要注意的是,参数列表和代码块是分离的,他们是独立变化的个体,如下有部分实例

1
2
3
4
loop { puts "Hi"}
loop() { puts "Hi"}
string.scan(/[^,]+/)
string.scan(/[^,]+/) { word puts word}

方法调用有没有代码块的区别在于方法内部是否有yield子句可以调用。如果有代码块,则可以调用,如果没有则不能。

假如将代码块作为方法调用的语法元素而不是作为参数来考虑,那么就能够对以迭代为基础的更多变化有更清晰的思路。

Times方法

times方法是一个Integer类的实例方法,这意味着可以在整型对象上调用它,根据整型的数值n来运行n次代码,并在方法的结尾返回数值n。

1
5.times { i puts "this is the #{i} times"}

times的行为说明了一个很美好的事实:使用yield运行一个代码块和从方法返回值是截然不同的事情。一个方法可以从0到无限多次调用他的yield语句。但是每次方法完成所有事情后,他将会严格的返回一次(确保没有错误的情况下)。

each方法到map方法

each方法很简单:在集合对象上运行each方法,他把集合中的元素逐个的去除传递给代码块。Ruby中有很多集合类,甚至像一些很像集合的类都支持each方法。

1
2
3
array = [1,2,3,4,5]
text = array.each { i puts "we got #{i}"}
print text

同时,each方法没有返回值,但是他会因为自身将取出的值传递给block,每取一次就会产生一个值。

each方法类似的是map方法,map方法一次遍历数组的一个元素,然后传递给代码块。

不同的地方在于,each方法返回它的接收者,map方法返回一个新数组。新数组的大小和原来的一致,但是元素和原始元素不同,新数组包含的元素由迭代代码块的返回值构成:

1
2
3
array = [1,2,3,4,5]
text = array.map {i i*10}
print text

新数组的映射结果中,其每一个元素都对应在原始数组的相同位置,只是经过了代码的处理。

在迭代分析过程中使用map是考虑到代码会返回一个值给调用它的方法,虽然仅只有方法可以调用yield并传递一个值,但是代码块能返回一个值,这个返回值作为调用yield的值返回。


  • Post title:Ruby-迭代器和代码块
  • Post author:Varsion
  • Create time:2020-09-07 15:15:53
  • Post link:https://blog.varsion.cn/post/1a6aef8c.html
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
Comments