Tim,
I like both of these ideas.  I agree, get-in2 seems to make sense as a
drop in replacement.

With update-in2 I prefer a new name, because I do occasionally write
code that constructs lists of functions.  I'd hate to get a weird bug
while doing this.

Sean

On Dec 10, 7:20 am, Timothy Pratley <timothyprat...@gmail.com> wrote:
> Hi,
>
> update-in is an especially useful function but I find the update
> function inevitably requires a check for nil. If I could supply a not-
> found value then my code would get better golf scores.
>
> When I reach for update-in, I usually want to pass it a numerical
> operator like inc or +, but these don't play nicely with nil. Another
> scenario is when I want to pass conj, which is fine if I want to
> create lists, except if I usually want the data structure to be
> something else. I've never come across a scenario where I didn't want
> to supply a not-found value, are there any common ones?
>
> If others have similar experience perhaps it is a candidate for
> change. Ideally I'd like to see a not-found parameter added to update-
> in and an extra arity overload for get-in as outlined below:
>
> (defn update-in2
>   "'Updates' a value in a nested associative structure, where ks is a
>   sequence of keys and f is a function that will take the old value
>   and any supplied args and return the new value, and returns a new
>   nested structure.  If any levels do not exist, hash-maps will be
>   created. If there is no value to update, default is supplied to f. "
>   ([m [k & ks] not-found f & args]
>    (if ks
>      (assoc m k (apply update-in2 (get m k) ks f args))
>      (assoc m k (apply f (get m k not-found) args)))))
>
> user=> (reduce #(update-in2 %1 [%2] 0 inc) {} ["fun" "counting"
> "words" "fun"])
> {"words" 1, "counting" 1, "fun" 2}
> user=> (reduce #(update-in2 %1 [(first %2)] [] conj (second %2)) {}
> [[:a 1] [:a 2] [:b 3]])
> {:b [3], :a [1 2]}
>
> (defn get-in2
>   "returns the value in a nested associative structure, where ks is a
> sequence of keys"
>   ([m ks]
>    (reduce get m ks))
>   ([m ks not-found]
>    (if-let [v (reduce get m ks)]
>      v
>      not-found)))
>
> user=> (get-in2 {:a {:b 1}} [:a :b] 0)
> 1
> user=> (get-in2 {:a {:b 1}} [:a :b :c] 0)
> 0
>
> Changing update-in would be a breaking change unfortunately. To avoid
> this you could consider checking the argument type for f to be
> function or value (making an assumption here that you would rarely
> want a function as the not-found value which is not 100% watertight).
> Or you could have a similarly named update-in-or function (which is
> less aesthetically pleasing), or maybe there is another even better
> way?
>
> Thanks for your consideration.
>
> Regards,
> Tim.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to