关于迭代器:retry语句在Ruby中如何工作?

How does the retry statement work in Ruby?

我刚刚开始使用Ruby,但是我遵循的手册似乎已经过时了。我一直在做一些研究,但一直找不到明确的答案。

手册在应作为循环的方法中使用了'retry'关键字,但该方法没有使用begin / rescue块,并且当您强制将'retry'关键字置于begin内时,行为似乎大不相同。 /救援块。

我尝试了很多事情:
-第一个方法是在方法开始时使用" begin"关键字,并在重试点使用" raise",然后分别使用" rescue";重试;结束;'。
-最后一个在外部使用了'begin / rescue'块,包装了方法的调用。

按照手册中的逻辑,只有最后一个可以正常工作。

有一些例子:

手册中的代码如下:

1
2
3
4
5
6
def WHILE(cond)
  return if not cond
  yield
  retry
end
i=0; WHILE(i<3) {print i; i+=1}

结果:
012

我尝试了以下方法:

1
2
3
4
5
6
7
8
9
10
def WHILE(cond)
  begin
    return if not cond
    yield
    raise
  rescue
    retry
  end
end
i=0; WHILE(i<3) {print i; i+=1}

结果:
无限数

1
2
3
4
5
def WHILE(cond)
  return if not cond
  yield
end
i=0; begin; WHILE(i<3) {print i; i+=1}; raise; rescue; retry; end

结果:
012(加上明显的无限循环,什么也不打印)

我希望您从这个存在的疑问中解脱出来,但这是我的结论。

在强制将'retry'关键字的begin / rescue块使用之前,可以以不再使用的方式使用它,尽管位于该方法内部,但仍重复该方法的调用。

现在,它只是跳转到"开始"语句。

但是我不确定,我需要确认。如果是这样,是否有任何形式可以恢复这种使用?

谢谢。


您的WHILE行为不像常规的WHILE,因为在您的情况下,i<3在调用时被评估一次。 WHILE语句每次对其进行评估。

如果要编写WHILE等效项,则条件必须是可以评估的条件,而不是已经评估的条件,这一点很重要。

您可以通过接受Proc作为条件来解决此问题:

1
2
3
4
5
6
7
def so_long_as(cond)
  loop do
    return unless cond.call

    yield
  end
end

然后,您可以这样称呼它:

1
2
3
4
5
i = 0
so_long_as(-> { i < 3 }) do
  print i
  i += 1
end

现在在其中打印012并正确终止。

需要注意的重要一点是,retry仅在begin / end上下文中起作用,而不是常规方法,现在您必须使用redo代替:

1
2
3
4
5
6
7
8
9
10
i = 0
redone = false
so_long_as(-> { i < 3 }) do
  print i
  unless (redone)
    redone = true
    redo
  end
  i += 1
end

现在在哪里打印0012

redoretry的工作方式已经发生了一些重大变化,值得一读。