Rubocop规则:永远不要使用'do'与多行'

Ond*_*cek 5 ruby while-loop rubocop

我有以下代码

  # colours a random cell with a correct colour
  def colour_random!
    while true do
      col, row = rand(columns), rand(rows)
      cell = self[row,col]
      if cell.empty? then
        cell.should_be_filled? ? cell.colour!(1) : cell.colour!(0)
        break
      end
    end
  end
Run Code Online (Sandbox Code Playgroud)

尽管它应该非常明显,但它正在做什么并不重要.关键是Rubocop给了我一个警告

切勿在多线时使用'do'

我为什么不这样做?那我该怎么办?

Aru*_*hit 16

while是一个关键字,因此您不需要传递块.没有do..end它将工作正常.以下是好的

  def colour_random!
    while true
      col, row = rand(columns), rand(rows)
      cell = self[row,col]
      if cell.empty? then
        cell.should_be_filled? ? cell.colour!(1) : cell.colour!(0)
        break
      end
    end
  end
Run Code Online (Sandbox Code Playgroud)

while是一个关键字,如果你传递一个块,比如do..end,它仍然可以按你的要求去做,不会抛出任何错误,而只是一个警告.但是,如果您尝试将一个ProcMethod对象传递给它,并动态尝试使用关键字将其转换为&,这可能会很危险,正如我们通常所做的那样.这意味着

# below code will work as expected just throwing an warning.
x = 2
while x < 2 do
  #code
end
Run Code Online (Sandbox Code Playgroud)

但如果你试图像下面那样错误地做

while &block # booom!! error
Run Code Online (Sandbox Code Playgroud)

原因是while关键字,它不支持任何to_proc方法来满足您的需求.所以它可能很危险.

Ruby风格指南还建议永远不要while/until condition do用于多线 while/until

我认为原因是Nobuyoshi Nakada邮件列表中说

loop是一种kernel采取阻止的方法.阿引入了新的局部变量范围.

  loop do
    a = 1
    break   
  end   
  p a #=> causes NameError
Run Code Online (Sandbox Code Playgroud)

while 没有.

  while 1
    a = 1
    break   
  end
  p a #=> 1
Run Code Online (Sandbox Code Playgroud)