退出内核#循环

时间:2015-01-04 18:05:33

标签: ruby

Kernel#loop documentation中,有一个示例使用break来突破循环。否则,文档会讨论如何发生StopIteration错误。

我试过了两个:

i=0
loop do
  puts i
  i+=1
  break if i==10
end

i=0
loop do
  puts i
  i+=1
  raise StopIteration if i==10
end

输出相同。两种方法之间是否存在差异?我认为应该有,否则为什么要费心定义一个错误类和随之而来的所有管理?

2 个答案:

答案 0 :(得分:3)

break是ruby中的关键字,它终止了最内部的循环,无论是loop还是for,还有一些(参见here)。

StopIteration是一个例外,由Kernel.loop捕获(请参阅here)。

因此,在您的方案中,它们是相同的,但在不同的情况下,它们将采取不同的行动:

puts "first run"
for i in 0..20 do
  puts i
  break if i==10
end
puts "first done"

puts "second run"
for i in 0..20 do
  puts i
  raise StopIteration if i==10
end
puts "second done" # <= will not be printed

以下是StopIteration无法使用break的情况:

puts "first run"

def first_run(i) # will not compile
  puts i
  break if i==10
end

i=0
loop do
  first_run(i)
  i+=1
end

puts "first done"

puts "second run"
def second_run(i)
  puts i
  raise StopIteration if i==10
end

i=0
loop do
  second_run(i)
  i+=1
end

puts "second done"

这是另一个用例,它使用Enumerator.next在枚举器到达结束时抛出StopIteration错误的事实:

enum = 5.times.to_enum
loop do
  p enum.next
end

将打印

0
1
2
3
4

感谢Cary这个例子。

答案 1 :(得分:1)

break关键字有两种用途。

首先:break关键字在块中时,会导致传递块的方法返回。如果将参数传递给break,则该方法的返回值将是该参数。这是一个例子:

def a
  puts 'entering method a'
  yield
  puts 'leaving method a'
end

result = a { break 50 }
puts result

这将打印:

entering method a
50

第二:break关键字可以导致whileuntilfor循环终止。这是一个例子:

i = 0
result =
  while i < 5
    i += 1
    puts i
    break 75 if i == 3
  end
puts result

这将打印:

1
2
3
75

Kernel#loop的示例使用了第一种情况,导致loop方法返回。

StopIteration是一个例外,就我所知,Kernel#loop一起使用。例如:

infinite_loop = Enumerator.new do |y|
  i = 0
  while true
    y << i
    i += 1
  end
end

infinite_loop.each do |x|
  puts x
  raise StopIteration if x == 4
end

失败,因为StopIteration未被捕获,但是:

x = 0
loop.each do
  puts x
  x += 1
  raise StopIteration if x == 4
end

抓住StopIteration并退出。