我正在http://learnyousomeerlang.com/errors-and-exceptions上阅读Erlang类(class)
我不明白这部分内容:
The Expression in between try and of is said to be protected. This means that any kind of exception happening within that call will be caught.
和
the protected part of an exception can't be tail recursive.
[...]
By putting your recursive calls between the of and catch, you are not in a protected part and you will benefit from Last Call Optimisation.
因此,我们不能在捕获异常的部分中放置递归调用?那么try catch块有什么意义呢?
在页面下方,我们在 protected 区域中有一个带有尾部递归函数的示例...
has_value(Val, Tree) ->
try has_value1(Val, Tree) of
false -> false
catch
true -> true
end.
has_value1(_, {node, 'nil'}) ->
false;
has_value1(Val, {node, {_, Val, _, _}}) ->
throw(true);
has_value1(Val, {node, {_, _, Left, Right}}) ->
has_value1(Val, Left),
has_value1(Val, Right).
他是不是意味着当我们处于try catch的 protected 部分时,我们需要使用函数将尾部递归代码包装到函数中吗?
最佳答案
So we can't put recursive calls in the part where the exceptions are catched ? What's the point of the try catch block then ?
函数不能在
try
内递归地调用自身;确切地说,如果是的话,就不会发生尾部优化。使用try
时,您必须能够在调用堆栈中的任何时候跳回到catch
块。这意味着必须有一个调用堆栈。如果使用了尾部调用优化,则不会有函数调用,因为它们现在只是循环。没有什么可以跳回去的。因此,try
块内部的递归必须真正递归。重点与大多数语言中的异常(exception)相同。您无法直接递归的事实有点烦人,但肯定不会删除异常处理的实用程序,因为:
Does he mean that we need to use a function to wrap tail recursive code into a function when we are in the protected part of a try catch ?
是的。它所需要的只是一个额外的功能,您可以很好地使用
try
,并且仍然可以获得TCO的好处。例子:% No TCO
func() ->
try
func()
catch _ ->
ok
end.
% TCO
func() ->
try
helper()
catch _ ->
ok
end.
helper() -> helper().
我不确定是否有一种简单的方法来确定在您希望TCO发生时是否意外递归。使用
try
时,您可能只需要保持警惕。
关于erlang - 在try catch block 中没有尾部递归代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17559946/