Erlang try-catch块中没有尾部递归代码?
我正在学校读二郎课 我不明白这部分: 介于try和of之间的表达式被称为受保护。这意味着该调用中发生的任何类型的异常都将被捕获 及 异常的受保护部分不能是尾部递归的 [……] 通过将递归调用放在of和catch之间,您就不在受保护的部分,您将从上次调用优化中受益 所以我们不能把递归调用放在捕获异常的部分?那么试一试又有什么意义呢 在下面的页面中,我们有一个例子,在受保护的部分有一个尾部递归函数Erlang try-catch块中没有尾部递归代码?,erlang,Erlang,我正在学校读二郎课 我不明白这部分: 介于try和of之间的表达式被称为受保护。这意味着该调用中发生的任何类型的异常都将被捕获 及 异常的受保护部分不能是尾部递归的 [……] 通过将递归调用放在of和catch之间,您就不在受保护的部分,您将从上次调用优化中受益 所以我们不能把递归调用放在捕获异常的部分?那么试一试又有什么意义呢 在下面的页面中,我们有一个例子,在受保护的部分有一个尾部递归函数 has_value(Val, Tree) -> try has_value1(Val, Tr
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的受保护部分时,我们需要使用一个函数将尾部递归代码包装到一个函数中吗
因此,我们不能将递归调用放在异常所在的部分
被抓住了?那么试一试又有什么意义呢
函数不能在try
中递归调用自身;或者更确切地说,尾部优化不会发生。使用try
时,必须能够在调用堆栈的任何点跳回catch
块。这意味着必须有一个调用堆栈。如果使用尾部调用优化,就不会有函数调用,因为它们现在只是循环。没有什么好回头的。因此try
块内部的递归必须真正递归
这一点与大多数语言中的异常相同。您不能直接递归这一事实有点麻烦,但肯定不会删除异常处理的实用程序,因为:
他是说我们需要使用一个函数来包装尾部递归吗
当我们处于try-catch的受保护部分时,将代码编码到函数中
?
对。它只需要一个额外的功能,您就可以使用试试很好,并且仍然可以获得TCO的好处。例如:
% No TCO
func() ->
try
func()
catch _ ->
ok
end.
% TCO
func() ->
try
helper()
catch _ ->
ok
end.
helper() -> helper().
我不确定是否有一种简单的方法来确定当您期望TCO发生时是否意外地递归。在使用try
时,您可能需要保持警惕。如果您希望优化尾部调用,则该调用必须在try-catching子句之外。你可以使用构造
your_fun(...) ->
...
try ... of <--- make notice of `of`
... ->
some_call(...)
catch
...
end.
has_value(Val, Tree) ->
has_value(Val, [Tree]).
has_value1(_, []) ->
false;
has_value1(Val, [{node, 'nil'} | Stack]) ->
has_value1(Val, Stack);
has_value1(Val, [{node, {_, Val, _, _}} | _]) ->
true;
has_value1(Val, [{node, {_, _, Left, Right}} | Stack]) ->
has_value1(Val, [Left, Right | Stack]).