この質問は古いことは知っていますが、差分リストについて誰も何も言わなかったので、追加して先頭に追加できるものが本当に欲しいと言っているので、差分リストが役立つように思えます。これらは Clojure では人気がないように見えますが、実装が非常に簡単で、finger ツリーよりもはるかに複雑ではないため、今、小さな差分リスト ライブラリを作成しました (そして、それをテストしました)。これらは O(1) 時間で連結されます (先頭または末尾に追加)。差分リストをリストに戻すには、O(n) のコストがかかるはずです。これは、多くの連結を行っている場合に適したトレードオフです。多くの連結を行っていない場合は、リストに固執するだけですよね? :)
この小さなライブラリの関数は次のとおりです。
dl:差分リストは実際には、それ自体の内容を引数と連結し、結果のリストを返す関数です。差分リストを作成するたびに、データ構造のように機能する小さな関数を作成しています。
dlempty:差分リストはその内容を引数に連結するだけなので、空の差分リストは恒等関数と同じです。
undl:差分リストの機能により、差分リストを nil で呼び出すだけで通常のリストに変換できるため、この関数は実際には必要ありません。それは便宜上のものです。
dlcons:リストの先頭にある項目を conses します -- 完全に必要というわけではありませんが、cons は十分に一般的な操作であり、ワンライナーです (ここのすべての関数と同様)。
dlappend: 2 つの相違リストを連結します。私はその定義が最も楽しいと思います - それをチェックしてください! :)
そして今、これがその小さなライブラリです。O(1) の追加/前置データ構造を提供する 5 つの 1 行の関数です。悪くないですよね?ああ、ラムダ計算の美しさ...
(defn dl
"Return a difference list for a list"
[l]
(fn [x] (concat l x)))
; Return an empty difference list
(def dlempty identity)
(defn undl
"Return a list for a difference list (just call the difference list with nil)"
[aDl]
(aDl nil))
(defn dlcons
"Cons an item onto a difference list"
[item aDl]
(fn [x] (cons item (aDl x))))
(defn dlappend
"Append two difference lists"
[dl1 dl2]
(fn [x] (dl1 (dl2 x))))
これで実際にそれを見ることができます:
(undl (dlappend (dl '(1 2 3)) (dl '(4 5 6))))
戻り値:
(1 2 3 4 5 6)
これも同じものを返します。
((dl '(1 2 3)) '(4 5 6))
違いリストを楽しんでください!
アップデート
理解するのがより難しいかもしれないいくつかの定義を次に示しますが、より良いと思います。
(defn dl [& elements] (fn [x] (concat elements x)))
(defn dl-un [l] (l nil))
(defn dl-concat [& lists] (fn [x] ((apply comp lists) x)))
これにより、次のようなことが言えます。
(dl-un (dl-concat (dl 1) (dl 2 3) (dl) (dl 4)))
どちらが返されますか
(1 2 3 4)