您可以显式地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;请注意,这是唯一的例外之一
名称中没有“错误”一词的类。)Ruby 在这方面遵循 Python
外部迭代技术。通过将循环终止视为异常,它使
你的循环逻辑非常简单;无需检查返回值
next 用于特殊的迭代结束值,无需调用某种
调用 next 之前的 next? 谓词。