prolog中的嵌套列表尾递归

时间:2014-08-03 05:23:34

标签: list recursion prolog

我试图执行嵌套列表尾递归而不使用使用内置的flatten 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).

这不是工作

感谢您的帮助

3 个答案:

答案 0 :(得分:0)

您可以在预处理步骤中使用flatten。将您的sum重命名为sum_flatten,然后添加

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

答案 1 :(得分:0)

如果没有教授如何解决这些问题的基础知识,你就会得到这种作业真的很奇怪。为什么需要重新实现库谓词呢?

您可以查看library predicate flatten/2的实施情况。请注意,它已被弃用。这是因为,我引用,"结束需要flatten/3经常表示,如append/3附加两个列表,一个糟糕的设计"。

即使您不使用flatten/2,它也会向您展示如何处理嵌套列表(这可能表明设计不合理,但无论如何)。

sum_nested([], Sum, Sum) :- !.
sum_nested([X|Xs], Acc, Sum) :- !,
    sum_nested(X, 0, Sum_Nested),
    Acc1 is Acc + Sum_Nested,
    sum_nested(Xs, Acc1, Sum).
sum_nested(Number, Acc, Sum) :-
    Sum is Number + Acc.

如果您希望谓词成功一次,则无法保留剪辑。您还应该注意到它不是严格的尾递归。你可以让它尾递归吗?什么样的输入会导致谓词失败?如果嵌套列表中有变量,会发生什么?

答案 2 :(得分:0)

避免展平的可能方法/ 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.