2017-04-10 54 views
1

所以我对于序言非常陌生,我必须将列表中的所有元素相加。在序言中添加列表的元素

listSum([],0). 
listSum([Head|Tail], Sum) :- listSum(Tail,TailSum), Sum is Head + TailSum. 

的目标是使该尾递归,我想知道,如果这是一个更好的方式来做到这一点比这

listSum([],0). 
listSum(List, Sum) :- listSum(List,Sum,0). 
listSum([H|T], Sum, S) :- S1 is S+H, listSum(T, Sum, S1). 
listSum([], Sum, S) :- Sum is S. 

或者是完全正常的呢?只是想看看是否有任何明显的方法来改进上面我错过的代码。

谢谢。

回答

2

这对我来说看起来非常好。你可以通过不做不必要的东西来节省自己的一些写作。首先,你从两个不同的地方得到0;从一个人就可以得到它。另外,“输出”论据应该在所有其他论据之后出现。

list_sum(L, S) :- 
    list_sum(L, 0, S). 

然后,你不需要is/2的基本情况:

list_sum([], S, S). 
list_sum([X|Xs], S0, S) :- 
    S1 is S0 + X, 
    list_sum(Xs, S1, S). 

当然,你可以决定实际保存在尾递归定义一个步骤:

list_sum([], 0). 
list_sum([X|Xs], S) :- 
    list_sum(Xs, X, S). 

list_sum([], S0, S) :- S is S0. 
list_sum([X|Xs], S0, S) :- 
    S1 is S0 + X, 
    list_sum(Xs, S1, S). 

您应该认识到第二个版本是一个折叠:

list_sum([], 0). 
list_sum([X|Xs], S) :- 
    foldl(add, Xs, X, S). 

add(X, Y, S) :- S is X+Y. 

或者,甚至直接:

list_sum(List, Sum) :- foldl(add, List, 0, Sum). 
+0

精彩,感谢您的快速和巨大的答复:) – mvantastic