打印出递归的每一步

时间:2017-10-29 12:10:37

标签: erlang erlang-shell

我正在使用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).

1 个答案:

答案 0 :(得分:4)

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

$('#dr_name').autocomplete({
            source: function( request, response ) {
                $.ajax({
                    type: "POST",
                    url : "<?php echo base_url()."index.php/counter_sale/dl"; ?>",
                    dataType: "json",
                    data: {
                       name: request.term
                    },
                     success: function( data ) {
                         response( $.map( data, function(item ) {
                            return {
                                value: item.name,
                                label: item.name,
                                dr_id:item.data_id,
                                return flase;
                            }
                        }));
                    }

                });
            },
            select: function(event, ui) {  
                $(this).val(ui.item.label);
                $("#dr_id").val(ui.item.dr_id);
                return false;  
            } ,

         change: function (event, ui) {
            val = $(this).val(); 
              exists = ui.item.label==val ? 0 : 1;
              if (exists) {
                $(this).val("");
                return false;
              }
        },

        autoFocus: true,
        minLength: 0        
    });