gpt4 book ai didi

erlang - 为什么 Erlang 会在存在高阶函数的情况下放弃生成堆栈跟踪?

转载 作者:行者123 更新时间:2023-12-04 23:01:38 27 4
gpt4 key购买 nike

当出现问题时,Erlang 会产生很好的堆栈跟踪,这在程序员想弄清楚为什么出错时很有帮助。然而,在存在高阶函数的情况下,产生堆栈跟踪的机制似乎不足。例如比较下面的两个示例(我在代码的注释中添加了生成的堆栈跟踪)。

我之前读过关于为惰性求值(例如在 Haskell 中)生成堆栈跟踪的困难。但是由于 Erlang 被评估为严格的,我原以为这里会有更好的结果。

我的问题是:是什么让高阶函数成为 Erlang 用于生成堆栈跟踪的机制的问题? 还有其他已知的技术可以产生更好的结果吗?

  1 -module(test).
2 -export([f/1,a/1]).
3
4 % Auxilary function to print stack trace (by throwing an exception).
5
6 s(X) when X < 0 -> 0.
7
8 % Example 1: Stack trace in presence of a higher order function.
9 %
10 % > test:f(1).
11 % ** exception error: no function clause matching test:s(1) (test.erl, line 6)
12 % in function test:g/2 (test.erl, line 15)
13
14 f(X) -> h(fun g/2,X).
15 g(X,Y) -> s(X) - Y.
16 h(I,X) -> I(X,3).
17
18 % Example 2: Stack trace for chain of 1st order function applications.
19 %
20 % > test:a(1).
21 % ** exception error: no function clause matching test:s(1) (test.erl, line 6)
22 % in function test:c/1 (test.erl, line 28)
23 % in call from test:b/1 (test.erl, line 27)
24 % in call from test:a/1 (test.erl, line 26)
25
26 a(X) -> b(X) + 1.
27 b(X) -> c(X) + 2.
28 c(X) -> s(X) + 3.

最佳答案

这不是使用高阶函数本身的结果,而是尾调用优化的结果。如果一个函数在返回之前做的最后一件事是调用另一个函数,那么 Erlang VM 会优化掉堆栈帧,因为它不再需要了。 (这就是为什么你可以在不溢出堆栈的情况下进行递归。)

在您的示例中,两个 fh执行尾调用,因此它们的堆栈帧在堆栈跟踪中不可见。另一方面,a , bc不要做尾调用,因为在返回给调用者之前,他们必须对他们正在调用的函数的结果执行加法。

关于erlang - 为什么 Erlang 会在存在高阶函数的情况下放弃生成堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21933171/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com