No concat?
johanatan opened this issue · 2 comments
Suppose I wanted to remove an item in the middle of a vector. The canonical way to do so in Clojure would be:
(defn vec-remove
"remove elem in coll"
[coll pos]
(vec (concat (subvec coll 0 pos) (subvec coll (inc pos)))))
yet there is no concat
operator for Subvec in ruminant. Is there a better way to achieve this?
In Clojure, if you call concat on two vectors then you end up with a different data structure:
user=> (type (concat [1 2] [3]))
clojure.lang.LazySeq
Ruminant does not include lazy sequences, however, and I suppose that is why there's no concat.
That being said, as you may know, when you call vec
, the lazy list is transformed into a vector. This isn't particularly fast though. It's done through one of the create methods of the PersistentVector
class (via vec and LazilyPersistentVector).
It's quite similar to calling into
:
(defn vec-remove
[coll pos]
(into (subvec coll 0 pos) (subvec coll (inc pos))))
So maybe we should add into
. That could be done as follows:
- If the first vector can be made transient (it is a proper
PersistentVector
), make it transient and conj all elements from the second vector onto it (viamakeIterator()
), and then make the result persistent - If the first vector cannot be made transient (it's a subvec), conj all elements from the second vector onto it.
This is what Clojure's into does.
An alternative approach would be to implement clojure.core.reducers.cat. The Clojure implementation only implements a few methods but it should be possible to implement all of PersistentVectorType
.
I think that both approaches might be fun exercises that shouldn't be too hard to do, if you feel like it. :)
To summarize. There are two approaches:
- We could add a method
into
to thePersistentVectorType
protocol. This would have a default implementation that conj'd elements of the second vector onto the first one. A specialized version forPersistentVector
would make use of transient vectors. - We could add a new struct
Cat
that would have two members of typePersistentVectorType