我刚刚开始使用Ruby,但是我遵循的手册似乎已经过时了。我一直在做一些研究,但一直找不到明确的答案。
该手册在应作为循环的方法中使用了'retry'关键字,但该方法在没有begin / rescue块的情况下使用,当您强制将'retry'关键字放入其中时,行为似乎大不相同一个开始/救援块。
我尝试了很多事情: -第一个方法是在方法开始时使用“ begin”关键字,并在重试点使用“ raise”,然后分别使用“ rescue”;重试;结束;'。 -最后一个在外部使用了'begin / rescue'块,包装了方法的调用。
按照手册中的逻辑,只有最后一个可以正常工作。
有一些例子:
手册中的代码如下:
def WHILE(cond)
return if not cond
yield
retry
end
i=0; WHILE(i<3) {print i; i+=1}
结果: 012
我尝试了以下操作:
def WHILE(cond)
begin
return if not cond
yield
raise
rescue
retry
end
end
i=0; WHILE(i<3) {print i; i+=1}
结果: 无限数
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块之前,它可以以一种不再使用的方式使用,重复方法的调用 位于该方法之内。
现在,它只是跳转到“开始”语句。
但是我不确定,我需要确认。如果是这样,是否有任何形式可以恢复这种使用?
谢谢。
答案 0 :(得分:3)
您的WHILE
的行为不像常规的while
,因为在您的情况下,i<3
是在通话时间一次进行评估的。 while
语句每次都会对其进行评估。
如果您想写一个while
等效项,那么您的条件应该是可以被评估的东西,而不是已经被 评估的东西,这一点很重要。
您可以通过接受Proc作为条件来解决此问题:
def so_long_as(cond)
loop do
return unless cond.call
yield
end
end
然后您这样称呼它:
i = 0
so_long_as(-> { i < 3 }) do
print i
i += 1
end
现在打印012
并正确终止的位置。
要注意的重要一点是retry
仅在begin
/ end
上下文中有效,而不是常规方法,现在您必须改为使用redo
:< / p>
i = 0
redone = false
so_long_as(-> { i < 3 }) do
print i
unless (redone)
redone = true
redo
end
i += 1
end
现在在哪里打印0012
。
答案 1 :(得分:0)
恕我直言,使用 loop
有点违背给定练习的目标,因此我还有另外两个使用 redo
或 retry
的解决方案,并且没有我想分享的循环。
如果您不知道我是怎么做的,我建议您在查看解决方案之前先尝试一下。
retry
def _while(cond, _loop=Class.new(RuntimeError))
raise _loop if cond.call
rescue _loop
yield
retry
end
i = 0
_while(-> { i < 3 }) do
print i
i += 1
end
redo
def _while(cond)
proc do
if cond.call
yield
redo
end
end.call
end
i = 0
_while(-> { i < 3 }) do
print i
i += 1
end