私は、Prologインタープリタが違いリストを特別なものとして扱うという考えを持っていると思います。そうではありません:Prologは相違点リストの概念を認識していません(構文糖を除くほとんどすべての概念の認識もありません)。彼は唯一の見ている:
L=-(|(a, |(b, |(c, |(d, |(e, []))))), |(d, |(e, [])))
-/2
と
|/2
はファンクタあり
、およびa
、b
、c
、d
、e
と[]
は定数です。
差分リストは単にプログラミング技術ある(例えば動的プログラミングためにも技術であるように、コンパイラが検出も異なる動的プログラミング・プログラムを処理することができません)。これは、表現の深い(部分的に)未統一部分を効率的に統一するために使用されます。
append/3
2つのリストが必要です。
%append(A,B,C).
append([],L,L).
append([H|T],L,[H|B]) :-
append(T,L,B).
しかし、これはO(n)ので実行されます:あなたは、最初に全体の最初のリストを反復処理する必要があるが、次のようにあなたはこれを行うことができます。リストに何千もの要素が含まれていると、時間がかかることがあります。
今、あなたはあなたがappend_diff/3
リストだけでなく、List
は、リストの先頭への参照である、とTail
はの終わりへの参照であるタプル-(List,Tail)
を供給します契約を自分で定義することができます統一リストではありません。この要件を満たす構造の例は、Tail-Tail
,[a|Tail]-Tail
,[1,4,2,5|Tail]-Tail
です。
今することができます効果的にappend_diff/3
でO(1)と:
append_diff(H1-T1,T1-T2,H1-T2).
なぜ? を統一すると、最初のリストの未統一テールが2番目のリストと統合されます。今や第2のリストの統一されていない尾が最終リストの末尾になります。だから、例えば取る:
append_diff([a|T1]-T1,[1,4,2,5|T2]-T2,L).
あなたは上記を参照としてあなたはT1
が[1,4,2,5|T2]
で統一します、述語を呼び出すと、我々はまた、T2
への参照を持っているので、今最初のリストは、[a|[1,4,2,5|T2]]
または短い[a,1,4,2,5|T2]
に崩壊し、 [a,1,4,2,5|T2]-T2
:オープンテールの新しい差異リストT2
を返すことができます(プロローグでははを返しました)。あなたは特別な意味を自分-
を与えるので、しかし、これが唯一である:プロローグ-
は、単に-
のであるため、それはないマイナスで、それは計算しないの違いなどPrologはファンクタにセマンティクスを添付していません。 -
の代わりに+
を使用した場合は、それほど大きな違いはありません。
質問に戻るには、L = -([a,b,c,d,e],[d,e])
以降でL = [a,b,c]
と言ってください。これらの2つの表現を統一することはできません。だからPrologはfalse
と言っています。
このセクションを読むための鍵は*を表します*。この本を見ると、トップレベルのAKAインタプリタでサンプルを使用することができますが、接頭辞は '? 'で始まります。例えば、[a、b、c] - []または[a、b、c、d、e] - [d、 e]または[a、b、c、d、e | T] - [d、e | T]または[a、b、c | T] -TここでTは任意のリストです。トップレベルで実行しますが、*あなたが思うべきものを表す*例を表すため、トップレベルの入力として使用するときのエラーです。 –
'L 'は' [a、b、c | [d、e]] - [d、e] 'と' [a、b、c] 'の両方にはなりません。これらは2つの異なる構造です。 – lurker
@lurker私はそれを今見ていますが、コメントの中に明確に示されているように、私は違いのリストの実用的な利益を見ていないのかもしれません。連結リストを使用する場合は、ウィレム・ヴァン・オンセム(Willem Van Onsem)が提案したように、* finalize *の手順が必要です。 –