为什么序言输出一个奇怪的树状列表?(Why prolog outputs a weird tree-

2019-10-17 22:57发布

在这种Prolog的代码,我打算列出前N素数,

(...)

biggerPrime(N,P) :-
    isPrime(N),
    P is N,
    !.

biggerPrime(N,P) :-
    N1 = N+1,
    biggerPrime(N1,P).

primeListAcc(0,A,R,R) :- !.

primeList(N,L) :-
    primeListAcc(N,1,[],L).

primeListAcc(N,A,L,R) :-
    N1 is N-1,
    biggerPrime(A,P),
    A1 is P+1,
    primeListAcc(N1,A1,[P|L],R).

如果我想名单下令向后正常工作:

?- primeList(5,L).
L = [11, 7, 5, 3, 2].

但是,如果我改变从代码的最后一行[P | L]到[L | P]是这样的:

primeListAcc(N,A,L,R) :-
        N1 is N-1,
        biggerPrime(A,P),
        A1 is P+1,
        primeListAcc(N1,A1,[L|P],R).

我得到:

?- primeList(5,L).
L = [[[[[[]|2]|3]|5]|7]|11].

我在想什么? 这是推动我疯了!

Answer 1:

太好了,所以你已经发现将元素添加到列表的末尾的问题。 在Prolog,我们可以做到这一点

add(X,L,Z):- L=[X|Z].

等待,是什么? 如何解读呢? 我们必须知道这里的调用约定。 我们预计 LZ进来作为非实例变量,我们安排L从现在指向一个新创建的利弊节点与X在其头部,并Z它的尾巴。 Z被实例化,可能的话,在将来的某个呼叫。

IOW我们在这里创建的是一个开放式的列表, L = [X|Z] = [X, ...]

primeList(N,L) :-
    primeListAcc(N,1,[],L).

primeListAcc(N,A,Z,L) :- N > 0,   % make it explicitly mutually-exclusive,
    N1 is N-1,                    %   do not rely on red cuts which are easily
    biggerPrime(A,P),             %   invalidated if clauses are re-arranged!
    A1 is P+1,                    
    L = [P|R],                    % make L be a new, open-ended node, holding P
    primeListAcc(N1,A1,Z,R).      % R, the tail of L, to be instantiated further

primeListAcc(0,A,R,R).            % keep the predicate's clauses together

我们现在可以看到Z是不是真的在这里需要的,因为它承载着[]向下的递归调用链,持平。 因此,我们可以重新写primeListAcc没有Z参数,因此其最终条款将是

primeListAcc(0,A,R):- R=[].

保持Z围绕作为非实例变量允许它稍后可能具有非空列表实例化,以及(当然,仅一次 (除非回溯发生))。 这就形成了“差异列表”技术的基础。


要回答你的问题的文字 -在这里,可以考虑这种互动成绩单:

1 ?- X=[a|b].

X = [a|b] 
2 ?- X=[a|b], Y=[X|c].

X = [a|b]
Y = [[a|b]|c] 

[a|b]的输出是一个缺点节点被刚刚打印方式中,当它的尾巴(这里, b不是一个列表。 原子,数字, 不是列表。



Answer 2:

回想一下,一个列表要么是空列表[]或仿函数的项'.' 和两个参数,它的第二个参数是一个列表。 的语法[P|Ps]是该术语简化符号'.'(P, Ps) ,这是一个列表,如果Ps是一个列表(如在您的示例的情况下)。 术语'.'(Ps, P) ,而另一方面,这也可以写成[Ps|P]如你正在做的),是不是列表,如果P不是一个列表。 你可以得到具有反向列表reverse/2



文章来源: Why prolog outputs a weird tree-like list?