打印出递归的每一步
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()
的匹配规范记录返回值。这清楚地显示了 sum
与 tail_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
我正在使用 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()
的匹配规范记录返回值。这清楚地显示了 sum
与 tail_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