【问题标题】:Print out each step of recursion打印出递归的每一步
【发布时间】:2018-04-10 12:47:49
【问题描述】:

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

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

这是我的两个函数:

普通递归:

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 erlang-shell


    【解决方案1】:

    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
    

    您还可以要求跟踪器使用返回 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
    

    【讨论】:

    • 我刚刚编辑了我的答案以包括return_trace。这应该对你更有用。跟踪是 Erlang VM 中我最喜欢的功能之一!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 2017-06-22
    • 2020-09-21
    • 2016-06-23
    • 1970-01-01
    相关资源
    最近更新 更多