What is catch and throw used for in Ruby?
在大多数其他语言中,catch和throw语句执行begin,rescue和raise语句在Ruby中执行的操作。 我知道你可以用这两个陈述来做到这一点:
1 2 3 | catch :done do puts"I'm done." end |
和
1 2 3 | if some_condition throw :done end |
但这有用的是什么? 有人可以给我一个Ruby中使用catch和throw语句的例子吗?
您可以使用它来打破嵌套循环。
1 2 3 4 5 6 7 8 9 10 | 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 |
如果你曾经使用过上面的break语句,它就会破坏内部循环。但是如果你想要打破嵌套循环,那么这个catch / throw会非常有用。我在这里用它来解决欧拉问题之一。
我一直在寻找一个很好的例子,直到我遇到Sinatra。
恕我直言,Sinatra为
在Sinatra中,您可以使用
1 | halt |
您还可以在暂停时指定状态...
1 | halt 410 |
还是身体......
1 | halt 'this will be the body' |
或两者...
1 | halt 401, 'go away!' |
halt方法使用throw实现。
1 2 3 4 | def halt(*response) response = response.first if response.length == 1 throw :halt, response end |
并被
Sinatra中有
在编写使用递归函数作用于嵌套数据结构的递归算法时,您可以使用
例如,假设您有一个正整数列表,并且您希望(出于某种原因)编写一个函数,如果满足以下任一条件,该函数将返回true:
- 列表中所有元素的总和大于100
- 列表中的某些元素如果等于5
让我们说你总是希望在列表中的单个短路传递中执行此检查,而不是执行
你可能会写一些像这样的代码(事实上,你可能已经在某些语言中用你的生活中的某些语言编写了这样的代码):
1 2 3 4 5 6 7 8 9 10 | def test(list) sum = 0 for i in list sum += i if i == 5 || sum > 100 return true end end return false end |
在大多数语言中,没有干净的等价物来打破使用递归函数的递归算法。但是在Ruby中,有!假设,您没有列表并且想要检查其元素是否包含五个或总和超过100,那么您有一棵树并且想要检查其叶子是否包含五或总和超过100,同时短路并返回一旦你知道了答案。
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | def _test_recurse(sum_so_far, node) if node.is_a? InternalNode for child_node in node.children sum_so_far = _test_recurse(sum_so_far, child_node) end return sum_so_far else # node.is_a? Leaf sum_so_far += node.value if node.value == 5 throw :passes_test elsif sum_so_far > 100 throw :passes_test else return sum_so_far end end end def test(tree) catch (:passes_test) do _test_recurse(0, tree) return false end return true end |
这里的