我正在使用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搜索方式无法找到该课程的回复)
答案 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
到目前为止,很好,你已经打印出了笛卡尔积。现在,您的作业也要求您使用yield
。 yield
的要点是“产生执行”,即暂时将控制传递给另一个代码块(可选地传递一个或多个参数)。
所以,虽然这个玩具示例不是真的,但不是直接打印上面的值,你可以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
这将输出每对值。