C#で永続的なコレクション(リストなど)を作成することを考えていますが、優れたAPIを見つけることができません。
Clojureの意味で「 persistent」を使用します。永続リストは、参照セマンティクスではなく値セマンティクスを持っているかのように動作するリストですが、大きな値型をコピーするオーバーヘッドは発生しません。永続コレクションは、コピーオンライトを使用して内部構造を共有します。擬似コード:
l1 = PersistentList()
l1.add("foo")
l1.add("bar")
l2 = l1
l1.add("baz")
print(l1) # ==> ["foo", "bar", "baz"]
print(l2) # ==> ["foo", "bar"]
# l1 and l2 share a common structure of ["foo", "bar"] to save memory
Clojureはそのようなデータ構造を使用しますが、さらにClojureではすべてのデータ構造が不変です。すべてのコピーオンライト処理を実行するにはオーバーヘッドが発生するため、Clojureは、データ構造を他のユーザーと共有していないことが確実な場合に使用できる一時的なデータ構造の形式で回避策を提供します。データ構造への唯一の参照がある場合は、すべてのコピーオンライトオーバーヘッドを実行するのではなく、直接変更してみませんか。
この効率を上げる1つの方法は、データ構造の参照カウントを維持することです(ただし、Clojureがそのように機能するとは思いません)。refcountが1の場合、唯一の参照を保持しているため、更新を破壊的に行います。refcountが高い場合は、他の誰かが値型のように動作するはずの参照を保持しているため、他のリファラーの邪魔にならないようにコピーオンライトを実行してください。
このようなデータ構造に対するAPIでは、refcountingを公開して、APIの使用性を大幅に低下させたり、refcountingを実行できなかったりして、すべての操作がCOWされた場合、またはAPIで不要なコピーオンライトのオーバーヘッドが発生する可能性があります。値型の動作が失われ、ユーザーはCOWを手動で実行するタイミングを管理する必要があります。
C#に構造体のコピーコンストラクターがある場合、これは可能です。実際のデータ構造への参照を含む構造体を定義し、その構造体のコピーコンストラクタとデストラクタですべてのincref()/ decref()呼び出しを実行できます。
APIユーザーを煩わせることなく、C#で参照カウントや構造体コピーコンストラクターのようなことを自動的に行う方法はありますか?
編集:
- 明確にするために、私はAPIについて質問しています。Clojureには、Javaで記述されたこれの実装がすでにあります。
- すべての操作でCOWされる実際のコレクションを参照する構造体を使用することにより、このようなインターフェイスを作成することは確かに可能です。refcountingの使用は、不要なCOWを回避するための最適化ですが、正常なAPIでは明らかに不可能です。