我正在与几个迭代器一起工作,在这些迭代器中,我必须按照以下方式做点事情(enum
是一个枚举器)
enums_with_zero << enum.rewind if enum.peek == 0
Run Code Online (Sandbox Code Playgroud)
通常可以正常工作,但这是在#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
Run Code Online (Sandbox Code Playgroud)
你可以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
Run Code Online (Sandbox Code Playgroud)
代码输出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!'
Run Code Online (Sandbox Code Playgroud)
循环的最后两行与此具有相同的作用,您可以改用它:
begin
a.next
rescue StopIteration
break
end
Run Code Online (Sandbox Code Playgroud)
需要说明的是,处理StopIteration
是Ruby处理迭代器末尾的预期方式。引自Matz的书《 Ruby编程语言》:
外部迭代器的使用非常简单:
next
每次需要另一个元素时都调用它。当没有剩余的元素时,next
将引发StopIteration
异常。这似乎很不寻常-预期的终止条件会引发异常,而不是意外的异常事件。(StopIteration
是的后裔StandardError
和IndexError
;请注意,它是没有在其名称中的“错误”,唯一的例外类之一。)红宝石遵循的Python在这种外部迭代技术。通过将循环终止视为一个例外,它使循环逻辑变得非常简单。无需检查返回值是否next
为特殊的迭代结束值,也无需在调用next?
之前调用某种 谓词next
。
归档时间: |
|
查看次数: |
50 次 |
最近记录: |