X = [1、2、3、4]のようなPrologのリストがある場合、要素5をリストの最後に追加してX = [1、2、3、4、5]にする方法を教えてください。
Append関数には2つのリストが必要です。つまり、AとBをリストCに連結するには、append(A、B、C)です。
一時リストY = [1、2、3、4]およびZ = [5]を使用してこれを実行し、append(Y、Z、X)を実行できますが、一時リストを使用するのは好きではありません。
通常の免責事項がここに適用されます-これは宿題ではなく、私はただPrologを学んでいます。
Prologの変数は一度だけ割り当てることができます。 Xの値が[1,2,3,4]になるとすぐに、別の値になることはありません。一時変数とappend/3は、あなたが言ったように、それを行う方法です。
そうは言っても、お勧めできないトリックが1つあります。 X = [1,2,3,4、Y]の場合、Y = 5を実行すると、Xに必要な値が設定されます。このテクニックは差分リストと呼ばれていると思います。
他の人が指摘したように、パフォーマンスの問題に悩まされることになります。
しかし、演習と同様に、append
を使用せずに、要素をリストの最後に追加できる述語を作成してみることにしました。
% add_tail(+List,+Element,-List)
% Add the given element to the end of the list, without using the "append" predicate.
add_tail([],X,[X]).
add_tail([H|T],X,[H|L]):-add_tail(T,X,L).
append
関数を単に使用することをお勧めします。組み込み関数として、手動で作成したものよりも高速になる可能性があります。
宣言的な解決策の1つは、差分リストを使用することです(ダニエルがその回答で示唆したように)。差分リストの名前は、通常、リストとその末尾の2つのリストの違いとして表されます。たとえば、空のリストはT-T
として表すことができます。要素1、2、および3を含むリストは、[1,2,3| T]-T
として表すことができます((-)/2
は標準の組み込みの挿入演算子です)。この表現の利点は、append/3
述語の単一のファクト定義を使用して、一定の時間で要素をリストに追加できることです。
append(L1-T1, T1-T2, L1-T2).
使用例:
?- append([1,2,3,4| T1]-T1, [5| T2]-T2, Result).
T1 = [5|T2],
Result = [1, 2, 3, 4, 5|T2]-T2.
必要に応じて、「通常の」リストと差分リスト間の変換は難しくありません。それは演習として残しておきます。
あなたは問題の間違った終わりを心配しています。構造の共有は、要素をリストの先頭に配置することによってのみ発生します。そのメソッドには、必要なパフォーマンス特性があります。リストの定義方法により、2つのリストを追加すると、最初のリスト全体がコピーされます。この場合、それがリスト全体になります。 1項目リストによって生成されるゴミは、明らかにそれよりはるかに小さくなります。
本当に追加する必要がある場合は、リストを逆方向に作成し、最後に一度逆にするとコストが安くなるか、差分リストを使用すると、効率的に最後に追加できます。
Prologでリストを変更することはできませんが、長さが指定されていないリストを作成できます。
main :-
A = [1,2,3,4|_].
次に、 nth0/3
SWI-Prolog内:
:- initialization(main).
main :-
A = [1,2,3,4|_],
nth0(4,A,5),
writeln(A).
この要素が挿入された後、A = [1,2,3,4,5|_]
。
リストの最後にアイテムを追加する関数を定義して、次のように使用することもできます。
:- initialization(main).
append_to_list(List,Item) :-
List = [Start|[To_add|Rest]],
nonvar(Start),
(var(To_add),To_add=Item;append_to_list([To_add|Rest],Item)).
main :-
A = [1,2,3|_],
append_to_list(A,4),
append_to_list(A,4),
writeln(A).
この例では、A = [1,2,3,4,4|_]
これら2つの項目が追加された後。
Prologにはリストのみを受け入れる追加があるため、リストの1つに要素を挿入するためにそれを使用しないのはなぜですか。つまり.
% E = element, L = list, R = result
% e.g. add_elem_in_list ([1,2,3,4], 5, R).
add_elem_in_list(L, E, R) :- append(L, [E], R).