Sé que esta pregunta es antigua, pero nadie dijo nada acerca de las listas de diferencias y como dices que realmente solo quieres algo que puedas agregar y preceder, parece que las listas de diferencias pueden ayudarte. No parecen populares en Clojure, pero son MUY fáciles de implementar y mucho menos complejos que los árboles de dedo, así que hice una pequeña biblioteca de lista de diferencias , e incluso la probé. Estos concatenan en O (1) tiempo (preceder o anexar). La conversión de una lista de a una lista debería costar O (n), que es una buena compensación si está haciendo mucha concatenación. Si no está haciendo una gran cantidad de concatenación , simplemente con las listas, ¿verdad? :)
Estas son las funciones en esta pequeña biblioteca:
dl: Una lista de diferencias es en realidad una función que concats sus propios contenidos con el argumento y devuelve la lista resultante. Cada vez que produce una lista de diferencias, está creando una pequeña función que actúa como una estructura de datos.
dlempty: Desde una lista diferencia simplemente concats su contenido al argumento , una lista vacía diferencia es lo mismo que la función identidad .
Undl: Debido a la diferencia que las listas de hacer, se puede convertir una lista diferencia a una lista de lo normal con sólo llamar con nula, por lo que esta función no es realmente necesario; es solo por conveniencia.
dlcons: conses un elemento al frente de la lista - no totalmente necesario, pero Consing es una operación bastante común y que es sólo una sola línea (como todas las funciones, aquí).
dlappend: concats dos listas de diferencias. Creo que su definición es lo más divertido - ¡compruébalo! :)
Y ahora, aquí está esa pequeña biblioteca - 5 funciones de una línea que le dan una O (1) anexar/anteponer la estructura de datos. No está mal, ¿eh? Ah, la belleza de Lambda Cálculo ...
(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))))
Usted puede verlo en acción con esto:
(undl (dlappend (dl '(1 2 3)) (dl '(4 5 6))))
que devuelve:
(1 2 3 4 5 6)
Esto también devuelve el Lo mismo:
((dl '(1 2 3)) '(4 5 6))
¡Diviértete con las listas de diferencias!
actualización
Estas son algunas definiciones que pueden ser más difíciles de entender, pero creo que son mejores:
(defn dl [& elements] (fn [x] (concat elements x)))
(defn dl-un [l] (l nil))
(defn dl-concat [& lists] (fn [x] ((apply comp lists) x)))
Esto te permite decir algo como esto:
(dl-un (dl-concat (dl 1) (dl 2 3) (dl) (dl 4)))
Que devolvería
(1 2 3 4)
sería negligente no señalar que el último ejemplo 'feo' se puede simplificar en una forma ligeramente menos fea: '(aplicar vector: foo [: bar: baz])' (acaba de sacar el 'contras '). Pero estoy de acuerdo que es un poco incómodo que, más allá de la solución '(vector ...)', básicamente hay 'concat'. Si solo hubiera una sintaxis azucarada/bonita para splatting arguments, en lugar de 'apply' (como' ~ @ 'pero no solo para macros) ... * suspiro * – chbrown