打印出递归的每一步

Print out each step of recursion

我正在使用 Erlang shell 来测试语言,我用两种方法编写了求和函数:一种是更经典的递归求和,另一种使用尾递归。第二个是线性的,第一个随着输入的大小而增长。

如何查看递归的每一步?我希望它在每一步都打印出当前值,以便我可以更好地了解正在发生的事情。

这是我的两个函数:

正常递归:

sum([]) -> 0;
sum([H|T]) -> H + sum(T).

尾递归:

tail_sum(List) -> tail_sum(List, 0).
tail_sum([], Sum) -> Sum;
tail_sum([H|T], Sum) -> tail_sum(T, H+Sum).

Erlang 中的 dbg 模块为此提供了一个有用的功能:跟踪。假设您的代码在模块 a:

中,下面是您如何跟踪这些函数

设置:

1> c(a). % load a.erl
{ok,a}
2> dbg:tracer(). % start the default trace message receiver
{ok,<0.71.0>}
3> dbg:p(all, c). % setup call tracing on all processes
{ok,[{matched,nonode@nohost,34}]}
4> dbg:tpl(a, '_', '_', []). % trace all functions in a
{ok,[{matched,nonode@nohost,5}]}

现在,无论何时调用模块中的任何函数,其名称和参数都将打印在 shell。

5> a:sum(lists:seq(1, 10)).
(<0.64.0>) call a:sum([1,2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([5,6,7,8,9,10])
(<0.64.0>) call a:sum([6,7,8,9,10])
(<0.64.0>) call a:sum([7,8,9,10])
(<0.64.0>) call a:sum("\b\t\n")
(<0.64.0>) call a:sum("\t\n")
(<0.64.0>) call a:sum("\n")
(<0.64.0>) call a:sum([])
55
6> a:tail_sum(lists:seq(1, 10)).
(<0.64.0>) call a:tail_sum([1,2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:tail_sum([1,2,3,4,5,6,7,8,9,10],0)
(<0.64.0>) call a:tail_sum([2,3,4,5,6,7,8,9,10],1)
(<0.64.0>) call a:tail_sum([3,4,5,6,7,8,9,10],3)
(<0.64.0>) call a:tail_sum([4,5,6,7,8,9,10],6)
(<0.64.0>) call a:tail_sum([5,6,7,8,9,10],10)
(<0.64.0>) call a:tail_sum([6,7,8,9,10],15)
(<0.64.0>) call a:tail_sum([7,8,9,10],21)
(<0.64.0>) call a:tail_sum("\b\t\n",28)
(<0.64.0>) call a:tail_sum("\t\n",36)
(<0.64.0>) call a:tail_sum("\n",45)
(<0.64.0>) call a:tail_sum([],55)
55

您还可以要求跟踪器使用 returns return_trace() 的匹配规范记录返回值。这清楚地显示了 sumtail_sum:

相比如何逐渐增加价值
7> dbg:tpl(a, '_', '_', [{'_',[],[{return_trace}]}]).
(<0.64.0>) call a:module_info()
{ok,[{matched,nonode@nohost,5},{saved,1}]}
8> a:sum(lists:seq(1, 10)).
(<0.64.0>) call a:sum([1,2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([3,4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([4,5,6,7,8,9,10])
(<0.64.0>) call a:sum([5,6,7,8,9,10])
(<0.64.0>) call a:sum([6,7,8,9,10])
(<0.64.0>) call a:sum([7,8,9,10])
(<0.64.0>) call a:sum("\b\t\n")
(<0.64.0>) call a:sum("\t\n")
(<0.64.0>) call a:sum("\n")
(<0.64.0>) call a:sum([])
(<0.64.0>) returned from a:sum/1 -> 0
(<0.64.0>) returned from a:sum/1 -> 10
(<0.64.0>) returned from a:sum/1 -> 19
(<0.64.0>) returned from a:sum/1 -> 27
(<0.64.0>) returned from a:sum/1 -> 34
(<0.64.0>) returned from a:sum/1 -> 40
(<0.64.0>) returned from a:sum/1 -> 45
(<0.64.0>) returned from a:sum/1 -> 49
(<0.64.0>) returned from a:sum/1 -> 52
(<0.64.0>) returned from a:sum/1 -> 54
(<0.64.0>) returned from a:sum/1 -> 55
55
9> a:tail_sum(lists:seq(1, 10)).
(<0.64.0>) call a:tail_sum([1,2,3,4,5,6,7,8,9,10])
(<0.64.0>) call a:tail_sum([1,2,3,4,5,6,7,8,9,10],0)
(<0.64.0>) call a:tail_sum([2,3,4,5,6,7,8,9,10],1)
(<0.64.0>) call a:tail_sum([3,4,5,6,7,8,9,10],3)
(<0.64.0>) call a:tail_sum([4,5,6,7,8,9,10],6)
(<0.64.0>) call a:tail_sum([5,6,7,8,9,10],10)
(<0.64.0>) call a:tail_sum([6,7,8,9,10],15)
(<0.64.0>) call a:tail_sum([7,8,9,10],21)
(<0.64.0>) call a:tail_sum("\b\t\n",28)
(<0.64.0>) call a:tail_sum("\t\n",36)
(<0.64.0>) call a:tail_sum("\n",45)
(<0.64.0>) call a:tail_sum([],55)
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/2 -> 55
(<0.64.0>) returned from a:tail_sum/1 -> 55
55