在prolog的深层列表中对原子元素求和

我是Prolog编程的初学者.我写了这个程序,用累加器对深度列表的原子求和.

    deep_sum(Xs, N) :- deep_sum(Xs, 0, N).
    deep_sum([], N, N).
    deep_sum([X|Y], M, N) :- atomic(X), Q is M + X, deep_sum(Y, Q, N).
    deep_sum([X|Y], M, N) :- M is P + Q, deep_sum(X, P, N), deep_sum(Y, Q, N).

为什么我会得到“错误:是/ 2:参数没有充分实例化”?

它没有累加器工作正常:

    deep_sum([], 0).
    deep_sum([X|Y], S) :- atomic(X), !, deep_sum(Y, Q), S is Q + X.
    deep_sum([X|Y], S) :- deep_sum(X, P), deep_sum(Y, Q), S is P + Q.

最佳答案 问题出在你的最后一句:

deep_sum([X|Y], M, N) :-  M is P+Q, deep_sum(X,P,N), deep_sum(Y,Q,N).

该错误的直接问题是当M是P Q时,P和Q都没有值.只是把它移到后面不会解决它,该条款有更多的问题.

我们来看看递归调用.单词中的deep_sum(X,P,N)表示“N是头部(X)的深度和,给定累加器P”.这里有两个问题:P没有值,N应该是整个列表的总和,而不仅仅是头部.

第二次递归调用中存在相同的问题.累加器Q还没有值,并且再次使用N作为结果.所以现在N有3个含义:头部的深度总和,尾部的深度总和,以及整个列表的深度总和!显然有些事情不对.

让我们试着说出递归规则应该如何表现.结果N应该等于a)电流累加器,b)磁头的深和和c)尾部的深和之和. a和b可以很容易地组合:简单地传入当前累加器作为递归调用的累加器:deep_sum(X,M,N1).这里我用另一个变量N1来保存这个结果.现在我们只需要用尾巴的深度总和来总结.同样,我们可以简单地将N1作为累加器传递给递归调用,并且所有内容都将按预期累积.

将所有内容放在一起,您的递归规则应如下所示:

deep_sum([X|Y], M, N) :- 
    deep_sum(X, M, N1), 
    deep_sum(Y, N1, N).

为了完整性,我的deep_sum / 3实现看起来像这样:

deep_sum(X, M, N) :- 
    number(X), 
    N is M + X.
deep_sum([], N, N).
deep_sum([X|Y], M, N) :- 
    deep_sum(X, M, N1), 
    deep_sum(Y, N1, N).

主要区别是:

>只有一个递归子句;处理数字的子句不需要递归.
> number / 1而不是atatomic / 1,所以你不要尝试添加字符串等.
>重新排列子句的顺序,一旦计算完成,就不会留下任何无用的选择点.

点赞