update-in oddness

47 views
Skip to first unread message

Heinz N. Gies

unread,
Jun 4, 2010, 1:37:38 AM6/4/10
to clo...@googlegroups.com
Update-in behaves oddly when getting an empty path. (update-in [] {1 2} (constantly {2 3})) returns {nil {2 3} 1 2} not {2 3} as I'd expect. get-in works well with empty pathes so I think this isn't a good behavior.

Regards,
Heinz

Joost

unread,
Jun 4, 2010, 5:15:59 AM6/4/10
to Clojure
On Jun 4, 7:37 am, "Heinz N. Gies" <he...@licenser.net> wrote:
> Update-in behaves oddly when getting an empty path. (update-in [] {1 2} (constantly {2 3})) returns {nil {2 3} 1 2} not {2 3} as I'd expect. get-in works well with empty pathes so I think this isn't a good behavior.

I don't know why you expect that to do anything - first of all, the
second argument to update-in should be a seq of keys. In any case, it
throws

nth not supported on this type: PersistentArrayMap
[Thrown class java.lang.UnsupportedOperationException]

Heinz N. Gies

unread,
Jun 4, 2010, 7:42:46 AM6/4/10
to clo...@googlegroups.com

Sorry I mixed arguments, it should be (update-in {1 2} [] (constantly {2 3}))

Joost

unread,
Jun 4, 2010, 8:03:58 AM6/4/10
to Clojure
On Jun 4, 1:42 pm, "Heinz N. Gies" <he...@licenser.net> wrote:
> Sorry I mixed arguments, it should be (update-in {1 2} [] (constantly {2 3}))

Yes, that gives {nil {2 3}, 1 2}

You're not giving any key in the key list, so that is the reason
there's a nil key now, and {2 3} is just the value that you give it,
since that's what ((constantly {2 3}) nil) returns.

Seems correct as far as the documentation of update-in is concerned.

Joost.

Joost

unread,
Jun 4, 2010, 8:08:40 AM6/4/10
to Clojure


On Jun 4, 2:03 pm, Joost <jo...@zeekat.nl> wrote:
> Seems correct as far as the documentation of update-in is concerned.

Addendum: though I think you've got a point in that inserting a nil
key is unexpected.
Personally, I don't really know what to expect from that expression.

Joost.

Heinz N. Gies

unread,
Jun 4, 2010, 8:11:04 AM6/4/10
to clo...@googlegroups.com
I'd expect that a empty key works on the entire  map, just as get-in with en empty key returns the entire map, this is kind of very important if you work with automatically with keys since otherwise you always have to handle the special case []. This is very annoying :(

here an example:

(if-let [r (butlast @path)]
     (do
(alter m update-in r dissoc (last @path))
(alter m update-in r assoc {:name @sr} c))
     (do
(alter m dissoc (last @path))
(alter m assoc {:name @sr} c)))

Heinz N. Gies

unread,
Jun 4, 2010, 10:04:07 AM6/4/10
to clo...@googlegroups.com

On Jun 4, 2010, at 14:11 , Heinz N. Gies wrote:

>
> On Jun 4, 2010, at 14:03 , Joost wrote:
>
>> On Jun 4, 1:42 pm, "Heinz N. Gies" <he...@licenser.net> wrote:
>>> Sorry I mixed arguments, it should be (update-in {1 2} [] (constantly {2 3}))
>>
>> Yes, that gives {nil {2 3}, 1 2}
>>
>> You're not giving any key in the key list, so that is the reason
>> there's a nil key now, and {2 3} is just the value that you give it,
>> since that's what ((constantly {2 3}) nil) returns.
>>
>> Seems correct as far as the documentation of update-in is concerned.


So for how I'd expect it to work:

(defn update-in*
([m [k & ks] f & args]
(if ks
(assoc m k (apply update-in* (get m k) ks f args))
(if k
(assoc m k (apply f (get m k) args))
(apply f m args)))))

user> (get-in {1 2} [])
{1 2}
user> (update-in* {1 2} [] assoc 1 3)
{1 3}

In opposite of how it works:

user> (update-in {1 2} [] assoc 1 3)
{nil {1 3}, 1 2}

Chouser

unread,
Jun 4, 2010, 10:23:19 AM6/4/10
to clo...@googlegroups.com

I agree with the spirit of your argument, but not your
implementation:

(update-in* {nil 2} [nil] (constantly 3))
;=> 3

Perhaps:

(defn update-in*
[m ks f & args]
(if-let [[k & mk] ks]
(if mk
(assoc m k (apply update-in* (get m k) mk f args))
(assoc m k (apply f (get m k) args)))
(apply f m args)))

(update-in* {nil 2} [nil] (constantly 3))
;=> {nil 3}

--Chouser
http://joyofclojure.com/

Heinz N. Gies

unread,
Jun 4, 2010, 10:28:02 AM6/4/10
to clo...@googlegroups.com
On Jun 4, 2010, at 16:23 , Chouser wrote:

>
> I agree with the spirit of your argument, but not your
> implementation:
>
> (update-in* {nil 2} [nil] (constantly 3))
> ;=> 3

As so often Chouser, you are of cause totally right :). I just realized the flaw when I was about to open a ticket but you were faster ;) well this are good news so since I don't have a CA signed yet (actually I do just not send it :P) so one could use your code as a fix.


Regards,
Heinz

Reply all
Reply to author
Forward
0 new messages