我知道这个问题很老,但是没有人说任何关于差异列表的事情,因为你说你真的只是想要一些你可以附加和前置的东西,听起来差异列表可能会对你有所帮助。它们在 Clojure 中似乎并不流行,但它们很容易实现,并且比手指树复杂得多,所以我刚刚做了一个微小的差异列表库(甚至测试了它)。这些在 O(1) 时间内连接(前置或附加)。将差异列表转换回列表应该花费您 O(n),如果您要进行大量连接,这是一个很好的权衡。如果你没有做很多连接,那么就坚持使用列表,对吧?:)
以下是这个小型库中的函数:
dl:差异列表实际上是一个函数,它将自己的内容与参数连接起来并返回结果列表。每次生成差异列表时,您都在创建一个类似于数据结构的小函数。
dlempty:由于差异列表只是将其内容连接到参数,因此空差异列表与恒等函数相同。
undl:由于差异列表的作用,您可以将差异列表转换为普通列表,只需使用 nil 调用它,因此实际上不需要此函数;这只是为了方便。
dlcons:将一个项目放在列表的前面——不是完全必要的,但 consing 是一个足够常见的操作,它只是一个单行(就像所有的函数一样,这里)。
dlappend:连接两个差异列表。我认为它的定义是最有趣的——看看吧!:)
现在,这是一个微型库—— 5 个单行函数,为您提供 O(1) 附加/前置数据结构。还不错吧?啊,Lambda微积分的美...
(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)