我正在使用一些迭代器,在这里我必须沿着这些行执行一些操作(enum是一个枚举器)

enums_with_zero << enum.rewind if enum.peek == 0

它通常工作正常,但这是在已经对枚举调用了#next几次之后。问题是enum可能在末尾,并且有几个值传递给enum,我遇到了enum.peek引发StopIteration的问题,因为enum已经完成。有没有一种方法可以让我在调用它之前检查enum.peekenum.next是否会导致StopIteration。比如会有这种行为的东西?
class Enumerator
  def has_next?
    begin
      peek && true
    rescue StopIteration
      false
    end
  end
end

最佳答案

您可以显式地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
当然,一旦你偷看了结尾,你就会被甩出圈外。如果不需要,可以使用whilerescue自定义行为。例如,如果要避免在浏览结束时退出,并在使用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是后代
注意这是唯一的例外
名称中没有“error”一词的类)。
外部迭代技术。通过将循环终止视为异常,它使
循环逻辑非常简单;不需要检查
StopIteration对于特殊的迭代结束值,不需要调用
StandardError调用IndexError之前的谓词。

关于ruby - 是否有内置方法来检查#next或#peek是否会引发StopIteration?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57963765/

10-10 07:23