Insert into an indexed seq

2,950 views
Skip to first unread message

Sean Devlin

unread,
Apr 27, 2010, 1:24:38 PM4/27/10
to Clojure
Is there a built in to insert a value into an "indexed" seq?

For example:

user=> (insert [:a :b :c :d] 2 :q)
(:a :b :q :c :d)

Not sure if I'm missing something simple...
Sean

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Sean Devlin

unread,
Apr 27, 2010, 1:31:35 PM4/27/10
to Clojure
Also, why does this work:
user=> (assoc [:a :b :c :d] 2 :q)
[:a :b :q :d]

And this doesn't:
user=> (dissoc [:a :b :c :d] 2)
#<CompilerException java.lang.ClassCastException:
clojure.lang.PersistentVector cannot be cast to
clojure.lang.IPersistentMap (NO_SOURCE_FILE:286)>

Annoying.

Chouser

unread,
Apr 27, 2010, 2:05:26 PM4/27/10
to clo...@googlegroups.com
On Tue, Apr 27, 2010 at 1:31 PM, Sean Devlin <francoi...@gmail.com> wrote:
> Is there a built in to insert a value into an "indexed" seq?
>
> For example:
>
> user=> (insert [:a :b :c :d] 2 :q)
> (:a :b :q :c :d)
>
> Not sure if I'm missing something simple...

That's a vector, which cannot efficiently splice internally, so
it's not supported directly. However, you can build a new vector
with your value included:

(apply conj [:a :b] :q [:c :d])
;=> [:a :b :q :c :d]

> Also, why does this work:
> user=> (assoc [:a :b :c :d] 2 :q)
> [:a :b :q :d]
>
> And this doesn't:
> user=> (dissoc [:a :b :c :d] 2)
> #<CompilerException java.lang.ClassCastException:
> clojure.lang.PersistentVector cannot be cast to
> clojure.lang.IPersistentMap (NO_SOURCE_FILE:286)>
>
> Annoying.

Again, vectors cannot efficiently insert or remove items except
from the right-hand end, though as you note items can replaced
internally.

(let [v [:a :b :c :d]]
(into (subvec v 0 2) (subvec v 3)))
;=> [:a :b :d]

There are immutable collections that support both numeric-indexed
lookups and internal splicing, they're just not currently included
with Clojure. See for example finger trees:

http://functionaljava.googlecode.com/svn/artifacts/2.21/javadoc/fj/data/Seq.html

--Chouser
http://joyofclojure.com/

Sean Devlin

unread,
Apr 27, 2010, 2:45:33 PM4/27/10
to Clojure
You're right, inserting into a vector is fundamentally slow.
Inserting into a list (must traverse elements) or String (Char Array)
isn't any better. I get why Clojure doesn't include certain
operations on certain data structures (e.g. assoc on a list), because
it's the wrong tool for the job. However, there are still problems
that require me to use an expensive operation.

Maybe I'm too focused on my current project, and wrong about how much
a typical person would use insert. Still, its absence seems like an
oversight.

Sean

On Apr 27, 2:05 pm, Chouser <chou...@gmail.com> wrote:
>        http://functionaljava.googlecode.com/svn/artifacts/2.21/javadoc/fj/da...
>
> --Chouserhttp://joyofclojure.com/

Mark J. Reed

unread,
Apr 27, 2010, 3:41:08 PM4/27/10
to clo...@googlegroups.com
I'm a bit surprised that it's not there already, at least in clojure.contrib, but it's not hard to write, at least for vectors:

(defn insert [vec pos item] 
    (apply merge (subvec vec 0 pos) item (subvec vec pos)))

--
Mark J. Reed <mark...@gmail.com>

Mark J. Reed

unread,
Apr 27, 2010, 3:53:37 PM4/27/10
to clo...@googlegroups.com
On Tue, Apr 27, 2010 at 3:41 PM, Mark J. Reed <mark...@gmail.com> wrote:
I'm a bit surprised that it's not there already, at least in clojure.contrib, but it's not hard to write, at least for vectors:

(defn insert [vec pos item] 
    (apply merge (subvec vec 0 pos) item (subvec vec pos)))

Er, that should be conj, not merge.  Though, perhaps surprisingly, it works as written.

-- 

James Reeves

unread,
Apr 28, 2010, 5:51:50 AM4/28/10
to Clojure
On Apr 27, 7:45 pm, Sean Devlin <francoisdev...@gmail.com> wrote:
> However, there are still problems
> that require me to use an expensive operation.

Could you give an example of such a problem? There may be another way
of solving it you have not considered.

- James

Rich Hickey

unread,
Apr 28, 2010, 7:21:58 AM4/28/10
to clo...@googlegroups.com

On Apr 27, 2010, at 2:45 PM, Sean Devlin wrote:

> You're right, inserting into a vector is fundamentally slow.
> Inserting into a list (must traverse elements) or String (Char Array)
> isn't any better. I get why Clojure doesn't include certain
> operations on certain data structures (e.g. assoc on a list), because
> it's the wrong tool for the job. However, there are still problems
> that require me to use an expensive operation.
>
> Maybe I'm too focused on my current project, and wrong about how much
> a typical person would use insert. Still, its absence seems like an
> oversight.
>

What are missing are finger trees, as Chouser said. Not having insert
on vector is not an oversight.

Rich
Reply all
Reply to author
Forward
0 new messages