RacketやSMLのような関数型言語では、通常、再帰呼び出しでリスト操作を実行します(パターンマッチング、リスト追加、リスト連結...)。ただし、関数型言語でのこれらの操作の一般的な実装はわかりません。リスト内の要素の作成、更新、削除などの操作は、リストのまったく新しいコピーを返しますか?私はかつて、関数型プログラミングの欠点についての例を本で読んだことがあります。つまり、データベースが更新されるたびに、データベースのまったく新しいコピーが返されます。
FPのデータは本質的に不変であるため、この例に疑問を投げかけました。したがって、既存のリストからリストを作成しても、まったく新しいコピーが作成されることはありません。代わりに、新しいリストは、フィルタリング基準に基づいた、他のリスト内の既存のオブジェクトへの参照の単なる異なるコレクションです。
たとえば、list A = [a,b,c]
、list B=[1,2,3]
、および既存のリストの最初の2つの要素を含む新しいリストを作成しましたC=[a,b,1,2]
。この新しいリストには、a,b,
fromA
および1,2
fromへの参照が含まれているだけB
です。データは不変であるため、新しいコピーであってはなりません。
したがって、リスト内の要素を更新するには、リスト内の要素を見つけ、新しい値を作成し、更新されたものを除いて古いリストと同じ要素で新しいリストを作成するのに、直線的な時間しかかかりません。新しいリストを作成するために、実行環境は前の要素の次のポインターを更新するだけです。リストが非アトミック要素(つまり、リスト、ツリー...)を保持していて、非アトミック要素の1つで1つのアトミック要素のみが更新される場合、このプロセスは、アトミック要素まで非アトミック要素に再帰的に適用されます。上記のように更新されます。これはどのように実装されるべきですか?
誰かが既存のリスト/追加/更新/削除/要素を使用してリストを作成するたびにリストの完全なコピーを作成する場合、彼らはそれを間違っていますね?
もう1つは、プログラム環境が更新されたとき(つまり、新しい変数に新しいキー/値エントリを追加して、後で参照できるようにする)、関数型プログラミングの不変のプロパティに違反しないということです。