Prolog インタープリターは差分リストを特別なものとして扱うという考えをお持ちだと思います。そうではありません: Prolog は差分リストの概念を認識していません (また、いくつかの構文上の砂糖を除くほぼすべての概念も認識していません)。彼は次のことしか見ていません。
L=-( |(a, |(b, |(c, |(d, |(e, []))))), |(d, |(e, [] )))
ここで-/2
、 と|/2
はファンクタでありa
、b
、 、c
、d
、e
および[]
は定数です。
差分リストは単なるプログラミング手法です (たとえば、動的プログラミングも手法であり、コンパイラーは動的プログラミング プログラムを別の方法で検出したり処理したりすることはできません)。式の奥にある (部分的に) 未統一な部分を効率的に統一するために使用されます。
2 つのリストが必要だとしappend/3
ます。これは次のように行うことができます。
%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
O(1)append_diff/3
で効果的にできるようになりました:
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]
のように折りたたまれ[a|[1,4,2,5|T2]]
ます。開いた尾を持つリスト。しかし、これはあなた自身が特別な意味を与えているからにすぎません: Prologは単にであり、マイナスではなく、差を計算しません。Prolog はファンクタにセマンティクスを付加しません。の代わりにを使用したとしても、わずかな違いはありませんでした。[a,1,4,2,5|T2]
T2
[a,1,4,2,5|T2]-T2
T2
-
-
-
+
-
したがって、質問に戻ると、Prolog にそれを述べL = -([a,b,c,d,e],[d,e])
、後でそれを述べるだけですL = [a,b,c]
。これで、これら 2 つの表現を統一できないことが明らかになりました。だからプロローグは言うfalse
。