Ruby 如何在没有其他可枚举类的情况下创建可枚举类?
几天前,我问了同样的问题,但不知怎么的,沟通没有发生。我重组了我的问题,希望我们能集中精力解决我需要解决的问题 问题基本上是这样的:如何创建一个不只是使用另一个可枚举类的可枚举类?作为我需要做的一个简单而完整的例子,请考虑这个类:Ruby 如何在没有其他可枚举类的情况下创建可枚举类?,ruby,Ruby,几天前,我问了同样的问题,但不知怎么的,沟通没有发生。我重组了我的问题,希望我们能集中精力解决我需要解决的问题 问题基本上是这样的:如何创建一个不只是使用另一个可枚举类的可枚举类?作为我需要做的一个简单而完整的例子,请考虑这个类: class MyClass include Enumerable def get_next return_val = rand.to_s if return_val.match(/33/) r
class MyClass
include Enumerable
def get_next
return_val = rand.to_s
if return_val.match(/33/)
return nil
else
return return_val
end
end
def each
# ??????
end
end
在这个类中,get_接下来计算一个随机值。然后,如果该值有两个相邻的3,则该方法返回nil。否则返回值。因此,您可以反复运行get_next,通常运行不到十次:
myob = MyClass.new
while not myob.get_next.nil?
puts 'got one'
end
事实上,get_下一步将通过数千个数据点进行搜索。当它找到下一项时,它返回一个相当大的对象。MyClass对象不可能将所有项都拖到一个数组中。一次只需要一个
事实上,我的课和上面的结构一样好。然而,我想以一种鲁比的方式实现它
因此,考虑到上述工人阶级,请填空。每个()中有什么内容可以使其成为可枚举类?类MyClass
class MyClass
include Enumerable
def enum
@enum ||= Enumerator.new do |y|
loop do
value = get_next
raise StopIteration.new("nil") if value.nil?
y << value
end
end
end
def each
return enum_for(:each) unless block_given?
enum.each(&Proc.new)
end
def get_next
return_val = rand.to_s
return_val.match(/33/) ? nil : return_val
end
end
mc = MyClass.new
mc.each { |e| puts e }
#⇒ 0.9354594959902887
# 0.6425492923024724
# 0.24551401459676037
# 0.17117672854168786
# 0.15611540754420283
# 0.3914491388594509
# 0.40243662946930725
# 0.3792875585148314
# 0.11978219941961588
# 0.49891129730441874
包括可枚举的
定义枚举
@enum | |=枚举器。新do | y|
环道
value=get\u next
如果value.nil,则引发StopIteration.new(“nil”)?
y类MyClass
包括可枚举的
定义枚举
@enum | |=枚举器。新do | y|
环道
value=get\u next
如果value.nil,则引发StopIteration.new(“nil”)?
Y
填空。每个()中都有哪些内容使其成为可枚举类
class MyClass
include Enumerable
def enum
@enum ||= Enumerator.new do |y|
loop do
value = get_next
raise StopIteration.new("nil") if value.nil?
y << value
end
end
end
def each
return enum_for(:each) unless block_given?
enum.each(&Proc.new)
end
def get_next
return_val = rand.to_s
return_val.match(/33/) ? nil : return_val
end
end
mc = MyClass.new
mc.each { |e| puts e }
#⇒ 0.9354594959902887
# 0.6425492923024724
# 0.24551401459676037
# 0.17117672854168786
# 0.15611540754420283
# 0.3914491388594509
# 0.40243662946930725
# 0.3792875585148314
# 0.11978219941961588
# 0.49891129730441874
医生说。因此,您可以这样做,只要它们不是nil
,就继续生成值
def each
while val = get_next
yield val
end
end
演示:
另一个演示(显示可枚举的中的方法):
因此,这就足以让它成为“可枚举的”,在某种意义上说,它成功地融入了可枚举的(我认为Ruby没有正式定义“可枚举的”)。顺便说一句,你的问题并不清楚你是否真的需要它。如果你只想用每个
检查值,那么你甚至不需要包括可枚举的
。所做的只是为您提供额外的方法,如map
和select
。即使是for
循环也可以通过每个
工作,而不包括可枚举的
:
irb(main):003:0> MyClass.new.map(&:to_f)
=> [0.6368065208805999, 0.6926393662295052, 0.9911564544581742, 0.35788099831068787]
irb(main):002:0> for e in MyClass.new
irb(main):003:1> puts e
irb(main):004:1> end
0.7638166357043203
0.18409214000273166
0.39757329498164495
0.14658393540113002
0.948396753859117
0.3157122887487579
0.4804571082701993
(但请注意,for
循环通常是不被鼓励的:,。我展示这一点只是为了进一步证明每个
的重要性,以及可枚举
对于基本迭代的不重要。)
填空。每个()中都有哪些内容使其成为可枚举类
class MyClass
include Enumerable
def enum
@enum ||= Enumerator.new do |y|
loop do
value = get_next
raise StopIteration.new("nil") if value.nil?
y << value
end
end
end
def each
return enum_for(:each) unless block_given?
enum.each(&Proc.new)
end
def get_next
return_val = rand.to_s
return_val.match(/33/) ? nil : return_val
end
end
mc = MyClass.new
mc.each { |e| puts e }
#⇒ 0.9354594959902887
# 0.6425492923024724
# 0.24551401459676037
# 0.17117672854168786
# 0.15611540754420283
# 0.3914491388594509
# 0.40243662946930725
# 0.3792875585148314
# 0.11978219941961588
# 0.49891129730441874
医生说。因此,您可以这样做,只要它们不是nil
,就继续生成值
def each
while val = get_next
yield val
end
end
演示:
另一个演示(显示可枚举的中的方法):
因此,这就足以让它成为“可枚举的”,在某种意义上说,它成功地融入了可枚举的(我认为Ruby没有正式定义“可枚举的”)。顺便说一句,你的问题并不清楚你是否真的需要它。如果你只想用每个
检查值,那么你甚至不需要包括可枚举的
。所做的只是为您提供额外的方法,如map
和select
。即使是for
循环也可以通过每个
工作,而不包括可枚举的
:
irb(main):003:0> MyClass.new.map(&:to_f)
=> [0.6368065208805999, 0.6926393662295052, 0.9911564544581742, 0.35788099831068787]
irb(main):002:0> for e in MyClass.new
irb(main):003:1> puts e
irb(main):004:1> end
0.7638166357043203
0.18409214000273166
0.39757329498164495
0.14658393540113002
0.948396753859117
0.3157122887487579
0.4804571082701993
(但请注意,for
循环通常是不被鼓励的:,。我展示这一点只是为了进一步证明每个
的重要性,以及可枚举
对于基本迭代的不重要。)看一看示例–调用Take(10)
只返回前10项,虽然数字是在无限循环中产生的。值得一读:看一看示例–调用Take(10)
只返回前10项,尽管数字是在无限循环中生成的。值得一读:太棒了!就像我需要的一样。谢谢好极了就像我需要的一样。谢谢如果您希望each
不带参数返回枚举数(就像stdlib enumerables一样),请将return to_enum,除非block_gived?
添加到方法顶部。此实现与next
契约不兼容,后者要求在没有要迭代的项时抛出StopIteration
。这就是说,这个实现与ruby完全不兼容,并且可能有许多隐藏的故障,这些故障将在以后成为生产运行时的错误。正确的方法是使用枚举器,正如我在回答中所显示的那样,这显然是错误的,甚至更危险。@mudasobwa,嗯?我正按照文件上说的做。“与ruby完全不兼容”?你是否忽略了我证明它有效的部分?顺便说一句,因为您的演示甚至没有使用Enumerable
中的任何内容。以及“next
contract”?它甚至没有next
方法。这是一个枚举器
的东西,而不是可枚举的
东西。如果您确实想要一个非块枚举数
结果,只需添加mwp所说的内容。你甚至可以自己做(只是时间更长)。然后还有一个next
,它将执行StopIteration
。你能展示一个实际的问题吗?当然。试着让它变得懒惰,好吧,我刚试过,效果很好。(顺便说一句,它已经很懒了,不是吗?)…如果您希望each
不带任何参数返回枚举数(就像stdlib enumerables一样),请将return to_enum,除非给出block_?
添加到方法顶部。此实现与next
契约不兼容,当没有要迭代的项时,期望抛出StopIteration
。也就是说,这个实现是不兼容的