Ruby产量示例说明?
我正在用Ruby学习SaaS课程。在一个练习中,我被要求使用迭代器、块和产量计算两个序列的笛卡尔积 我的结论是,纯粹是猜测和错误,这似乎是可行的。但我不知道怎么做。我似乎理解基本块和产量用法,但是这个呢?一点也不Ruby产量示例说明?,ruby,block,yield,enumerable,Ruby,Block,Yield,Enumerable,我正在用Ruby学习SaaS课程。在一个练习中,我被要求使用迭代器、块和产量计算两个序列的笛卡尔积 我的结论是,纯粹是猜测和错误,这似乎是可行的。但我不知道怎么做。我似乎理解基本块和产量用法,但是这个呢?一点也不 class CartProd include Enumerable def initialize(a,b) @a = a @b = b end def each @a.each{|ae| @
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
请给我这样的傻瓜解释一下好吗
(注:我将所需的类名改为CartProd,这样做的人就无法通过谷歌搜索找到答案)你到底不明白什么?您已经创建了一个迭代器,可以生成所有可能的元素对。如果您通过
CartProd#每个
a块,它将执行a.length*b.length
次。这就像在任何其他编程语言中将两个不同的for
循环折叠成另一个循环一样 你到底不明白什么?您已经创建了一个迭代器,可以生成所有可能的元素对。如果您通过CartProd#每个
a块,它将执行a.length*b.length
次。这就像在任何其他编程语言中将两个不同的for
循环折叠成另一个循环一样 yield只是将(yields)控制传递给作为方法调用一部分传入的代码块。yield关键字后面的值作为参数传递到块中。一旦块完成执行,它将返回控制
因此,在您的示例中,您可以这样称呼#每个:
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
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只是将控制权传递给作为方法调用一部分传入的代码块。yield关键字后面的值作为参数传递到块中。一旦块完成执行,它将返回控制
因此,在您的示例中,您可以这样称呼#每个:
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
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
这将输出每对值。让我们一步一步地构建它。我们将把它从类上下文中去掉,从而简化一些事情 对于本例,直观地认为迭代器是传统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惯用迭代器样式来替换它,显式地提供要执行的块(即do…end
块):
到目前为止,很好,您已经打印出您的笛卡尔积。现在,您的作业要求您也使用yield
。yield
的要点是“yield execution”,即暂时将控制权传递给另一个代码块(可选地传递一个或多个参数)
因此,尽管在这个玩具示例中没有必要这样做,但您可以生成值,并让调用方提供一个接受该值的块并打印它,而不是像上面那样直接打印该值
可能是这样的:
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
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
可以这样称呼:
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
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
为内部循环的每次运行提供产品,并且生成的值由调用方提供的块打印。让我们一步一步地构建它。我们将把它从类上下文中去掉,从而简化一些事情
对于本例,直观地认为迭代器是传统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惯用迭代器样式来替换它,显式地提供要执行的块(即do…end
块):
到目前为止,很好,您已经打印出您的笛卡尔积。现在,您的作业要求您也使用yield
。yield
的要点是“yield execution”,即暂时将控制权传递给另一个代码块(可选地传递一个或多个参数)
因此,尽管在这个玩具示例中没有必要这样做,但您可以生成值,并让调用方提供一个接受该值的块并打印它,而不是像上面那样直接打印该值
可能是这样的:
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
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
可以这样称呼:
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
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
为内部循环的每次运行提供产品,并且生成的值由调用者提供的块打印。也许我不完全理解yield在那里做什么如果你的方法调用有一个块,它只是在执行一个块。您在yield调用中指定的任何参数都将传递给block。yield[ae,be]
通知调用代码返回值为[ae,be]
。仔细阅读有助于你理解这个例子是如何工作的。我想我现在明白了!因此,有一个名为each的块,由可枚举模块定义,用于完成任务。对吗?到目前为止,我所读到的关于收益率的用法是有道理的。也许我不明白收益率到底在做什么。如果你的方法调用有一个块,它只是在执行一个块。您在yield调用中指定的任何参数都将传递给block。yield[ae,be]
通知调用代码返回值为[ae,be]
。仔细阅读有助于你理解这个例子是如何工作的。我想我现在明白了!因此,有一个名为each的块,由可枚举模块定义,用于完成任务。对吗?这与我到目前为止所读到的有关yield用法的内容是有道理的。旁注:类变量@a和@b是有害的(试着用两个实例进行实验)。它们应该被替换为@a和@b。谢谢,我会更正的。所以@@定义了类变量和@instance变量。顺便说一句,包含可枚举的
行是不必要的。@manzoid:除非CartProd本身是可枚举的。@muistooshort:这是一个很好的观点。如果您想混合使用可枚举设施,请确定。我认为上面提到的赋值有点不同:“使用迭代器、块和产量计算两个序列的笛卡尔乘积”,所以我认为最好保持简单