什么是Ruby中的catch和throw?

age*_*217 31 ruby

在大多数其他语言中,catch和throw语句执行begin,rescue和raise语句在Ruby中执行的操作.我知道你可以用这两个陈述来做到这一点:

catch :done do
  puts "I'm done."
end
Run Code Online (Sandbox Code Playgroud)

if some_condition
  throw :done
end
Run Code Online (Sandbox Code Playgroud)

但这有用的是什么?有人可以给我一个Ruby中使用catch和throw语句的例子吗?

bra*_*boy 34

您可以使用它来打破嵌套循环.

INFINITY = 1.0 / 0.0
catch (:done) do
  1.upto(INFINITY) do |i|
    1.upto(INFINITY) do |j|
      if some_condition
        throw :done
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你曾经使用过上面的break语句,它就会破坏内部循环.但是如果你想要打破嵌套循环,那么这个catch/throw会非常有用.我在这里用它来解决欧拉问题之一.


Sim*_*tti 21

我一直在寻找一个很好的例子,直到我遇到Sinatra.恕我直言,Sinatra公开了一个非常有趣的示例用法catch.

在Sinatra,您可以随时使用,立即终止请求halt.

halt
Run Code Online (Sandbox Code Playgroud)

您还可以在暂停时指定状态...

halt 410
Run Code Online (Sandbox Code Playgroud)

还是身体......

halt 'this will be the body'
Run Code Online (Sandbox Code Playgroud)

或两者...

halt 401, 'go away!'
Run Code Online (Sandbox Code Playgroud)

halt方法使用throw实现.

def halt(*response)
  response = response.first if response.length == 1
  throw :halt, response
end
Run Code Online (Sandbox Code Playgroud)

通过invoke方法捕获.

:haltSinatra 有几种用途.您可以阅读源代码以获取更多示例.

  • @jsz为一,它更快 - 堆栈帧不必沿着"抛出的符号"携带,并且没有创建对象.轻量级非线性流量控制. (3认同)
  • @mezis是现代的GOTO (3认同)
  • 抛出它是一种更优雅的方式,可以使用类似异常的系统作为控制流. (2认同)