首先,我们先为Array新增一个迭代方法iterate!,如下:
class Array
def iterate!
self.each_with_index do |m,i|
self[i] = yield(m)*10
end
end
end
array = [1,2,3,4]
那么我们看看应该怎么调用?
array.iterate! do |m|
m **=2
end
p array #=> [10,40,90,160]
与属性不同,在方法中不需要指定block的名字,而是使用yield
来调用。yield
会执行block中的代码。同时,注意我们是怎么把n(each_with_index当前处理的数字)传给yield的。传给yield的参数即对应了block中的参数(||中的部分)。现在m
就能被block调用并在yield调用中返回m**2
。
整个调用如下:
- 一个整数组成的数组调用iterate!
- 当yield被调用时,把m(第一次为1,第二次为2,…)传给block
- block对m进行m**2。因为是最后一行,自动作为结果返回。
- yield得到block的结果,并把值*10后重写到array里。
- 数据中每个对象执行相同操作。
那么这样写的输出是什么呢?
array.iterate! do |m|
m **=2
m+2
end
p array #=> [30,60,110,180]
即把block中的m+2的值传给了yield,此时的m已经做过平方的计算了。然后再*10后重写到array里。
那么这样写的输入又如何呢?
array.iterate! do |m|
m **=2
m+2
n = 100000
end
p array #=> [1000000,1000000,1000000,1000000]
即把block中的n的值传给了yield。
继续往下尝试
k = 0
array.iterate! do |m|
m **=2
m+2
n = 100000
k
end
p array #=> [0,0,0,0]
即把block中的k的值传给了yield。
由此可知,ruby会把block中最后一个表达式的值传给迭代方法中的yield,然后再进行计算。
甚至可以这样:
class Array
def iterate!
self.each_with_index do |m,i|
$a ||= []
$a << yield(m)*10
end
end
end
$a
array = [1,2,3,4]
k = 0.9
array.iterate! do |m|
m **=2
end
p $a #=> [10, 40, 90, 160]
网友评论