List prolog上的嵌套列表尾部递归

List prolog上的嵌套列表尾部递归,list,recursion,prolog,List,Recursion,Prolog,我正在尝试执行嵌套列表尾部递归,而不使用内置的flantfunc 我的示例是列表中所有值的总和 sum(LIST,SUM):-sum(LIST,0,SUM). sum([],SUM,SUM). sum([A|LIST],RES,SUM):-sum(A,RES2,SUM), RES1 is RES+RES2,sum(LIST,RES1,SUM). sum([H|LIST],RES,SUM):-RES1 is RES+H,sum(LIST,RES1,SUM). 例如,在展平列表上 [trace]

我正在尝试执行嵌套列表尾部递归,而不使用内置的
flant
func

我的示例是列表中所有值的总和

sum(LIST,SUM):-sum(LIST,0,SUM).
sum([],SUM,SUM).
sum([A|LIST],RES,SUM):-sum(A,RES2,SUM), RES1 is RES+RES2,sum(LIST,RES1,SUM).
sum([H|LIST],RES,SUM):-RES1 is RES+H,sum(LIST,RES1,SUM).
例如,在展平列表上

[trace] 13 ?- sum([1,2,3,4,5,6],Sum).
Sum = 21.
但如果我尝试嵌套列表

[trace] 12 ?- sum([1,2,[3,4],5,6],Sum).
它不起作用了


感谢您的帮助

您只需在预处理步骤中使用
展平
。将您的
sum
重命名为,例如,
sum\u flatten
,然后添加

sum(List, Sum) :- 
     flatten(List, FlattenList),
     sum_flatten(FlattenList, Sum).

这真的很奇怪,你得到这样的任务,却没有被教授如何着手解决它们的基本知识。为什么需要重新实现库谓词

您可以查看的实现。请注意,它已被弃用。这是因为,我引用,“最终需要
flant/3
通常表明,像
append/3
附加两个列表一样,一个糟糕的设计”

即使您不使用
flant/2
,它也会告诉您如何处理嵌套列表(这可能表明设计不好,但无论如何)


如果您希望谓词成功一次,就不能保留剪切。您还应该注意到,它不是严格意义上的尾部递归。你能把它做成尾巴递归的吗?什么样的输入会导致谓词失败?如果嵌套列表中有变量,会发生什么情况?

避免扁平化的一种可能方法/2是创建(某种)成员/2,如

leafs([E|L], R) :- !, (leafs(E, R) ; leafs(L, R)).
leafs(E, E) :- E \= [].
现在库(聚合)可以像

sum(LIST, SUM) :- aggregate(sum(E), leafs(LIST, E), SUM).
给予

?- sum([1,[[2],3]],X).
X = 6.

对我明白。。但我真的想实现这一点,而不使用内置的展平函数。。感谢您应该使用
append/2
而不是扁平化(至少在SWI Prolog中提供),同时,也可以使用
sum\u list/2
append(嵌套列表,列表),sum\u list(列表,总和)
感谢Boris。。。所以没有办法实现严格的尾部递归嵌套列表?每个递归算法都可以转换为严格的尾部递归,然后再进行迭代。@avis如果你能想出一个严格的尾部递归版本,你应该把它作为你问题的答案发布!
?- sum([1,[[2],3]],X).
X = 6.