Proposal: New fn assoc-in-with

32 views
Skip to first unread message

Sean Devlin

unread,
Jan 21, 2010, 10:11:51 PM1/21/10
to Clojure
Sometimes you don't want assoc-in to create a hash-map. Sometimes you
wish it could create a sorted map.

Just finished working on something with Alexy Khrabrov & Chouser on
IRC, and the three of us are wondering if the result might be
generally useful.

(defn assoc-in-with
"supply a default-map instead of a hash-map"
[m default-map [k & ks] v]
(if ks
(assoc m k (assoc-in-as (get m k default-map) default-map ks v))
(assoc m k v)))

Also, is there room for a sister fn update-in-with?

Thoughts?
Sean

Chouser

unread,
Jan 22, 2010, 8:57:31 AM1/22/10
to clo...@googlegroups.com
On Thu, Jan 21, 2010 at 10:11 PM, Sean Devlin <francoi...@gmail.com> wrote:
> Sometimes you don't want assoc-in to create a hash-map.  Sometimes you
> wish it could create a sorted map.
>
> Just finished working on something with Alexy Khrabrov & Chouser on
> IRC, and the three of us are wondering if the result might be
> generally useful.
>
> (defn assoc-in-with
>  "supply a default-map instead of a hash-map"
>  [m default-map [k & ks] v]
>  (if ks
>    (assoc m k (assoc-in-as (get m k default-map) default-map ks v))
>    (assoc m k v)))

As I mentioned in IRC, this could actually be a 4-argument
version of 'assoc-in' instead of a new function. Assuming of
course Rich likes the idea.

--Chouser
http://joyofclojure.com/

Rich Hickey

unread,
Jan 29, 2010, 8:44:18 AM1/29/10
to clo...@googlegroups.com

Where would the default go? Also, need it be a map, vs anything
associative (e.g. a vector)?

Rich

Sean Devlin

unread,
Jan 29, 2010, 8:53:25 AM1/29/10
to Clojure
The following doesn't currently work:

user=> (assoc [] 1 :a)
#<CompilerException java.lang.IndexOutOfBoundsException>

So I say this should be map only. Granted, assoc-in already has this
issue.

Also, what do you mean by your question "Where would the default go"?
I don't understand what you're getting at yet.

Sean


On Jan 29, 8:44 am, Rich Hickey <richhic...@gmail.com> wrote:
> On Fri, Jan 22, 2010 at 8:57 AM, Chouser <chou...@gmail.com> wrote:

Chouser

unread,
Jan 29, 2010, 9:40:57 AM1/29/10
to clo...@googlegroups.com

Since update-in could use this pattern as well, I don't think the
default should go after the value (or update fn) position.
I think where Sean put it is fine -- after the collection, before
the vector of keys.

I don't see why it needs to be restricted to a map -- all the
normal assoc rules apply.

--Chouser
http://joyofclojure.com/

Rich Hickey

unread,
Feb 3, 2010, 11:05:53 AM2/3/10
to clo...@googlegroups.com

As soon as you are varidic with update-in I think you'll need new
names, i.e. can't just add another arity to assoc-in and update-in.

> I don't see why it needs to be restricted to a map -- all the
> normal assoc rules apply.
>

Right.

I wonder though, if a single default coll is sufficient. There are
potentially multiple levels to the structure, using different data
structures at each level.

Rich

Rich Hickey

unread,
Feb 3, 2010, 11:03:12 AM2/3/10
to clo...@googlegroups.com
On Fri, Jan 29, 2010 at 8:53 AM, Sean Devlin <francoi...@gmail.com> wrote:
> The following doesn't currently work:
>
> user=> (assoc [] 1 :a)
> #<CompilerException java.lang.IndexOutOfBoundsException>
>

But this does:

user=> (assoc [] 0 :a)

[:a]

> So I say this should be map only.

I don't think so.

> Also, what do you mean by your question "Where would the default go"?
> I don't understand what you're getting at yet.
>

Just a question of arg order.

Rich

Sean Devlin

unread,
Feb 4, 2010, 9:02:10 AM2/4/10
to Clojure
Some "Thinking out loud" here...

My last concern with assoc-in & arrays has to do with how it is
currently used for maps. The way it creates elegant nested structures
is nice, and it requires very little understanding of the current
structure of the map.

However, assoc-in has a few more constraints when dealing w/ arrays,
and the end user does have to keep track of array structure. Granted
they have to do this anyway by the nature of arrays. I personally
always use conj when creating a vector of vectors, so I don't se much
of a use case (Hmmm... Sparse Matrix? That's better as a map...).

I DO see a great use case for update-in-with working on vectors, so
maybe assoc-in-with working on vectors should be implemented simply
for symmetry.

I dunno. That's all I've got right now.

On Feb 3, 11:03 am, Rich Hickey <richhic...@gmail.com> wrote:

ajuc

unread,
Feb 4, 2010, 10:25:24 AM2/4/10
to Clojure
Maybe sth like that

(defn assoc-in-maybe-creating [coll keys creator-fns value] ...)

so it can be used:

(assoc-in-maybe-creating
[ {:a (sorted-map :X 1, :Y 2, :Z 3)
:c (sorted-map :X 1, :Z 3)}
{:b (sorted-map :X 1, :Y 2, :Z 3)}
{:f (sorted-map :X 1, :Y 2)}]
[0 :b :X]
[vector hashmap sorted-map]
1)

returning

[ {:a (sorted-map :X 1, :Y 2, :Z 3)
:b (sorted-map :X 1)
:c (sorted-map :X 1, :Z 3)}
{:b (sorted-map :X 1, :Y 2, :Z 3)}
{:f (sorted-map :X 1, :Y 2)}]

or like that

(assoc-in-maybe-creating
[]
[0 :a :Y]
[vector hashmap (fn []
(struct-map CustomStruct
:required-field1 value1 :required-field2 value2))]
2)

Name is temporary, I couldn't think of better one.

Reply all
Reply to author
Forward
0 new messages