我正在与一些迭代器一起工作,在这些迭代器中,我必须按照以下原则进行操作(enum
是枚举器)
enums_with_zero << enum.rewind if enum.peek == 0
通常可以正常工作,但这是在枚举上已经多次调用#next
之后。问题是enum
可能在最后,并且为enum
传递了一些值,我遇到了enum.peek
引发StopIteration
的问题,因为{ {1}}完成。有没有一种方法可以让我看管enum
或enum.peek
导致enum.next
的原因,然后再调用它。像这样的行为?
StopIteration
答案 0 :(得分:5)
您可以显式地rescue
StopIteration
,但是也有一种想法,loop
方法通过简单地退出循环来在内部挽救StopIteration
异常。 (在loop
内部,raise StopIteration
与break
具有相同的作用。)
当您尝试窥视结尾时,此代码仅退出循环:
a = %w(a b c d e).to_enum
loop do
print a.peek
a.next
end
代码输出abcde
。 (它也透明地举起和营救StopIteration
。)
因此,如果您想窥视结尾时只想忽略StopIteration
异常,只需使用loop
。
当然,一旦您窥视了结尾,您将被甩出循环。如果您不希望这样做,可以使用while
和rescue
自定义行为。例如,如果要避免越过终点而退出,而在使用next
越过终点而退出时,可以执行以下操作:
a = %w(a b c d e).to_enum
while true
begin
print a.peek
rescue StopIteration
print "\nTried to peek past the end of the enum.\nWe're gonna overlook that.\n"
end
x = a.next rescue $!
break if x.class == StopIteration
end
p 'All done!'
循环的最后两行与此具有相同的作用,您可以改用它:
begin
a.next
rescue StopIteration
break
end
需要说明的一点是,处理StopIteration
是Ruby处理迭代器末尾的预期方式。引自Matz的书 Ruby编程语言:
外部迭代器的使用非常简单:每次需要另一个时,只需调用
next
元件。如果没有其他元素,next
将引发StopIteration
异常。 这似乎很不正常-预期终止会引发异常 状况,而不是意料之外的异常事件。 (StopIteration
是后代StandardError
和IndexError
中;请注意,这是唯一的例外之一 名称中没有单词“ error”的类。)Ruby在此遵循Python 外部迭代技术。通过将循环终止视为异常, 您的循环逻辑非常简单;无需检查的返回值next
获得特殊的迭代结束值,则无需调用某种next?
谓词,然后再调用next
。