erlang - 在try catch block 中没有尾部递归代码?

标签 erlang

我正在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/

相关文章:

Erlang:成功案例和错误处理作为事务

erlang - 可以在Erlang消息上发送哪种类型的消息?

erlang - Erlang 中的列表累加器

erlang - 消息的时间顺序

c++ - 在解码嵌套的元素列表时使用 ei_decode_list

java - 如何以编程方式提取视频帧?

ubuntu - 在 Ubuntu 上安装 RabbitMq 时出现 Erlang 依赖问题

sockets - 从套接字和另一个 Erlang 进程接收

serialization - term_to_binary 的字符串版本

memory-management - 如何衡量 Erlang 垃圾收集器的性能?