Ruby yield示例解释?

时间:2012-10-06 10:32:59

标签: ruby block yield enumerable

我正在使用Ruby进行SaaS课程。在练习中,我被要求通过使用迭代器,块和产量来计算两个序列的笛卡尔积。

我最终得到了这个,通过纯粹的猜测和错误,它似乎工作。但我不确定如何。我似乎理解基本块和产量用法,但是这个?完全没有。

class CartProd
  include Enumerable
  def initialize(a,b)
        @a = a
        @b = b
  end
  def each
        @a.each{|ae|
                @b.each{|be|
                        yield [ae,be]
                }
        }
  end
end

对于像我这样的菜鸟的一些解释,拜托?

(PS:我将所需的课程名称更改为CartProd,因此通过Google搜索方式无法找到该课程的回复)

3 个答案:

答案 0 :(得分:7)

让我们一步一步地构建它。我们将通过将它从类上下文中删除来简化一些事情。

对于这个例子,可以直观地将迭代器视为传统for循环的更强大的替代品。

首先,这是一个for循环版本:

seq1 = (0..2)
seq2 = (0..2)
for x in seq1
  for y in seq2
    p [x,y] # shorthand for puts [x, y].inspect
  end
end  

现在让我们用更多Ruby-idiomatic迭代器样式替换它,显式提供要执行的块(即do...end块):

seq1.each do |x|
  seq2.each do |y|
    p [x,y]
  end
end

到目前为止,很好,你已经打印出了笛卡尔积。现在,您的作业也要求您使用yieldyield的要点是“产生执行”,即暂时将控制传递给另一个代码块(可选地传递一个或多个参数)。

所以,虽然这个玩具示例不是真的,但不是直接打印上面的值,你可以yield值,让调用者提供一个接受的块该值并打印出来。

这可能是这样的:

 def prod(seq1, seq2)
    seq1.each do |x|
      seq2.each do |y|
        yield [x,y]
      end
    end
  end

可以这样调用:

prod (1..2), (1..2) do |prod| p prod end

yield为内循环的每次运行提供产品,并且由调用者提供的块打印出产生的值。

答案 1 :(得分:0)

你究竟在这里不明白什么?您已经创建了一个迭代器,它可以生成所有可能的元素对。如果您通过CartProd#each一个块,它将被执行a.length*b.length次。这就像在任何其他编程语言中将两个不同的for个循环折叠成另一个循环。

答案 2 :(得分:0)

yield 只是将(yield)控制传递给作为方法调用的一部分传入的代码块。 yield关键字后面的值作为参数传递给块。一旦块完成执行,它就会传回控制权。

因此,在您的示例中,您可以像这样调用#each:

CartProd.new([1, 2], [3, 4]).each do |pair|
  # control is yielded to this block
  p pair
  # control is returned at end of block
end

这将输出每对值。