1

この 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].

私は何が欠けていますか?これは私を怒らせています!

4

2 に答える 2

2

リストは空リスト[]か、ファンクター'.'と 2 つの引数を持つ項で、2 番目の引数がリストであることを思い出してください。構文は、 がリストの場合はリストである[P|Ps]という用語の簡略表記です(例の場合のように)。一方、(あなたがやっているように)と書くこともできるという用語は、がリストでない場合、リストではありません。で逆リストを取得できます。'.'(P, Ps)Ps'.'(Ps, P)[Ps|P]Preverse/2

于 2013-03-31T19:59:47.437 に答える
1

リストの最後に要素を追加する際の問題を発見しました。Prolog では、

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

待って、何?読み方は?ここで呼び出し規約を知っておく必要があります。インスタンス化されていない変数として と が入ってくることを期待 Lし、今後は新しく作成されたコンスノードを先頭と末尾で指すように手配します。おそらく、将来の呼び出しでインスタンス化されます。ZLXZZ

ここで作成するのは、制限のないリストです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に運ぶため、実際には必要ないことがわかります。したがって、引数なし[]で書き直すことができるので、その最後の節はprimeListAccZ

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

インスタンス化されていない変数として保持Zすることで、後で空でないリストを使用してインスタンス化することもできます (もちろん、1だけです(バックトラッキングが発生しない限り))。これが「差分リスト」手法の基礎となります。


あなたの文字通りの質問に答えるために - ここで、この対話のトランスクリプトを考えてみましょう:

1 ?- X=[a|b].

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

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

[a|b]出力は、コンス ノードの末尾 (ここではb) がリストでない場合に出力される方法です。数としてのアトムはリストではありません。

于 2013-04-01T12:41:14.567 に答える