ruby - 是否有内置方法来检查 #next 或 #peek 是否会引发 StopIteration?
问题描述
我正在使用一些迭代器,我必须按照这些思路做一些事情(enum
是一个枚举器)
enums_with_zero << enum.rewind if enum.peek == 0
这通常工作正常,但这是在#next
枚举已经被调用了几次之后。与此有关的问题是enum
可能在最后并且为 传递了一些值enum
,我遇到了由于完成而enum.peek
引发的问题。有没有一种方法可以让我在打电话之前检查是否或会导致。例如,会有这种行为的东西?StopIteration
enum
enum.peek
enum.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
.
当然,一旦你窥视到最后,你就会被甩出循环。如果您不希望这样,您可以使用while
andrescue
来自定义行为。例如,如果您想避免在查看结束时退出,并在使用 迭代结束时退出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 的书The Ruby Programming Language:
外部迭代器使用起来非常简单:
next
每次需要另一个元素时调用。当没有剩余元素时,next
将引发StopIteration
异常。这可能看起来不寻常——针对预期的终止条件而不是意外和异常事件引发异常。(StopIteration
是StandardError
and的后代IndexError
;请注意,它是唯一一个名称中没有“error”一词的异常类。) Ruby 在这种外部迭代技术中遵循 Python。通过将循环终止视为异常,它使您的循环逻辑非常简单;不需要检查返回值next
是否有特殊的迭代结束值,也不需要在调用之前调用某种next?
谓词next
.
推荐阅读
- python - 有一个带有两个引号的字符串?
- python-3.x - 如何检查我的 python 路径是否设置正确?
- java - 如何计算电话号码的位数?
- ffmpeg - 如何使用 netcat 流式传输 H.264?
- angular - 在 Angular CLI 中生成的 Git
- reactjs - 在反应中创建条件样式
- node.js - 为什么不记名令牌给出错误“无法读取未定义的属性'拆分'”?
- python - Python Tkinter 命令优先级
- visual-studio - 卡在 Visual Studio 中运行的 Flutter 项目
- r - 使用 R 中的正则表达式在文本中提取年份,在带宽内