是否有内置方法来检查#next 或#peek 是否会引发 StopIteration?
Is there a built-in way to check if #next or #peek will raise 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
和 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 的书 The Ruby Programming Language:
External iterators are quite simple to use: just call next
each time you want another
element. When there are no more elements left, next
will raise a StopIteration
exception.
This may seem unusual—an exception is raised for an expected termination
condition rather than an unexpected and exceptional event. (StopIteration
is a descendant
of StandardError
and IndexError
; note that it is one of the only exception
classes that does not have the word “error” in its name.) Ruby follows Python in this
external iteration technique. By treating loop termination as an exception, it makes
your looping logic extremely simple; there is no need to check the return value of
next
for a special end-of-iteration value, and there is no need to call some kind of
next?
predicate before calling next
.
我正在使用一些迭代器,我必须按照这些思路做一些事情(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
和 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 的书 The Ruby Programming Language:
External iterators are quite simple to use: just call
next
each time you want another element. When there are no more elements left,next
will raise aStopIteration
exception. This may seem unusual—an exception is raised for an expected termination condition rather than an unexpected and exceptional event. (StopIteration
is a descendant ofStandardError
andIndexError
; note that it is one of the only exception classes that does not have the word “error” in its name.) Ruby follows Python in this external iteration technique. By treating loop termination as an exception, it makes your looping logic extremely simple; there is no need to check the return value ofnext
for a special end-of-iteration value, and there is no need to call some kind ofnext?
predicate before callingnext
.