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