我正在http://learnyousomeerlang.com/errors-and-exceptions上阅读Erlang课程
我不明白这一部分:
据说try和of之间的表达受到保护.这意味着将捕获该调用中发生的任何类型的异常.
和
异常的受保护部分不能是尾递归.
[...]
通过在of和catch之间进行递归调用,您不在受保护的部分中,并且您将受益于Last Call Optimization.
所以我们不能在捕获异常的部分放置递归调用?那么try catch块有什么意义呢?
在页面下面我们有一个示例,在受保护的部分中有一个尾递归函数...
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).
Run Code Online (Sandbox Code Playgroud)
他是否意味着当我们处于try catch的受保护部分时,我们需要使用函数将尾递归代码包装到函数中?
Chr*_*ris 14
所以我们不能在捕获异常的部分放置递归调用?那么try catch块有什么意义呢?
函数不能递归调用自身内部try; 或者说,如果确实如此,尾部优化将不会发生.使用时try,您必须能够catch在调用堆栈的任何位置跳回到块.这也就意味着,有有是一个调用堆栈.如果使用尾调用优化,则没有函数调用,因为它们现在只是循环.什么都没有跳回去.因此,try块内的递归必须真正递归.
这一点与大多数语言中的例外情况相同.您不能直接递归的事实有点令人烦恼,但肯定不会删除异常处理的效用,因为:
他是否意味着当我们处于try catch的受保护部分时,我们需要使用函数将尾递归代码包装到函数中?
是.所需要的只是一个额外的功能,您可以使用try得很好,仍然可以获得TCO的好处.例:
% No TCO
func() ->
try
func()
catch _ ->
ok
end.
% TCO
func() ->
try
helper()
catch _ ->
ok
end.
helper() -> helper().
Run Code Online (Sandbox Code Playgroud)
我不确定是否有一种简单的方法可以确定在您预期TCO发生时是否意外复发.你可能只需要在使用时保持警惕try.