我正在使用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).
答案 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()
的匹配规范记录返回的值。这清楚地显示了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
:
$('#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
});