ruby中的block

首先,我们先为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]

你可能感兴趣的:(ruby中的block)