从Integer#次内调用的Ruby yield没有返回计算的块



有一个非常简单的问题,为什么当我将块定义为这样时:

def test
yield
end
a=test{7} => a=7

但是当我定义一个像这样的块时

def test(n)
n.times{ yield }
end
a=test(4){7} => 4

为什么返回值变成n不屈服?

它返回来自Integer#times的值(恰好与您调用该方法的数字相同,可以在Rubinius源代码或RubySpec上看到),而不是块返回值。

由于Integer#times多次调用块,因此基本上有两个替代方案:

  1. 将数组上所有调用的结果合并并返回。

    def test(n)
      result = []
      n.times { |current| result << yield(current) }
      result
    end
    # Or, leveranging Enumerator#map:
    def test(n)
      n.times.map { |current| yield(current) }
    end
    # Or, still shorter, by forwarding the block:
    def test(n, &block)
      n.times.map(&block)
    end
    test(4) { |n| n * 2 } # => [0, 2, 4, 6]
    
  2. 将块返回的最后一个值存储在变量上,并返回:

    def test(n)
      result = nil
      n.times { |current| result = yield(current) }
      result
    end
    test(4) { |n| n * 2 } # => 6
    

如果查看源代码,times方法将返回它运行的次数,而不是它运行的块的结果。

最新更新