ZetCode

Ruby redo 关键字

最后修改日期:2025 年 4 月 27 日

本教程解释了如何使用 Ruby 的 redo 关键字。它会重新开始循环的当前迭代,而不检查循环条件。

redo 关键字会导致当前循环迭代重新开始。与 next 不同,它不会评估循环条件或移至下一个项目。

当您需要重试操作而不推进循环状态时,redo 非常有用。它适用于 whileuntilfor 和迭代器方法。

基本的 redo 示例

这个简单的例子演示了 redo 的基本行为。当满足某个条件时,循环会重新开始。

basic_redo.rb
count = 0

while count < 5
  count += 1
  puts "Count: #{count}"
  
  if count == 3
    puts "Redoing iteration"
    redo
  end
end

循环通常会运行 5 次,但在计数为 3 时出现的 redo 会导致该迭代重新开始。请注意,循环条件不会被重新检查。

带有输入验证的 redo

redo 通常用于输入验证。此示例会持续要求输入,直到提供有效数据为止。

input_validation.rb
3.times do |i|
  print "Enter a positive number: "
  input = gets.chomp.to_i
  
  if input <= 0
    puts "Invalid input! Try again."
    redo
  end
  
  puts "You entered: #{input}"
end

如果输入无效,redo 会重新开始当前迭代。直到收到有效输入,循环计数器才会递增。

嵌套循环中的 redo

在嵌套循环中,redo 只影响最内层的循环。此示例显示了它在嵌套结构中的行为。

nested_loops.rb
outer = 0
inner = 0

while outer < 2
  outer += 1
  puts "Outer: #{outer}"
  
  while inner < 3
    inner += 1
    puts "  Inner: #{inner}"
    
    if inner == 2
      puts "  Redoing inner loop"
      redo
    end
  end
  
  inner = 0
end

redo 只影响内层循环。内层循环完成后,外层循环会正常继续。

带有重试逻辑的 redo

此示例使用 redo 为不可靠的操作实现重试逻辑。它会立即重试失败的操作。

retry_logic.rb
attempts = 0

5.times do |i|
  attempts += 1
  puts "Attempt #{attempts} (iteration #{i + 1})"
  
  # Simulate random failure
  if rand < 0.4
    puts "Operation failed! Retrying..."
    redo
  end
  
  puts "Operation succeeded"
end

每次失败都会触发一次 redo,重新开始当前迭代。只有在操作成功后,循环计数器才会递增。

redo 与 next 的区别

此示例将 redonext 进行对比,以突出它们在循环控制中的不同行为。

redo_vs_next.rb
puts "Using redo:"
3.times do |i|
  puts "Start iteration #{i}"
  
  if i == 1
    puts "Redoing..."
    redo
  end
  
  puts "End iteration #{i}"
end

puts "\nUsing next:"
3.times do |i|
  puts "Start iteration #{i}"
  
  if i == 1
    puts "Skipping..."
    next
  end
  
  puts "End iteration #{i}"
end

redo 会重新开始当前迭代,而 next 会跳到下一个迭代。请注意两种情况下的输出有何不同。

带有 until 循环的 redo

redountil 循环中的工作方式与 while 循环类似。此示例展示了它在负逻辑中的行为。

until_loop.rb
value = 0

until value > 3
  value += 1
  puts "Value: #{value}"
  
  if value == 2
    puts "Redoing until check"
    redo
  end
end

redo 会重新开始迭代,而不会重新评估 until 条件。循环将继续,直到条件变为 true。

带有 yield 的方法中的 redo

这个高级示例展示了 redo 在一个 yield 到块的方法中的行为。redo 会影响块的执行。

method_with_yield.rb
def retry_operation
  attempts = 0
  
  3.times do |i|
    attempts += 1
    puts "Attempt #{attempts}"
    
    yield i
    
    if attempts < 3
      puts "Retrying..."
      redo
    end
  end
end

retry_operation do |i|
  puts "Block execution #{i}"
  raise "Error" if i == 0 && attempts < 2
rescue
  puts "Rescued error"
end

方法内的 redo 会重新启动块的执行。结合错误处理,这可以创建强大的重试逻辑。

来源

Ruby 关键字文档

本教程通过实际示例,涵盖了 Ruby 的 redo 关键字,展示了输入验证、重试逻辑和循环控制模式。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Ruby 教程