Seconded; I like the intention of both changes, and do something similar in a lot of my code (e.g., parsing functions that take an extra arg if the parse is unsuccessful). Also, testing the type of update-in2's second arg is a bad idea, imo.
As for the breaking change of adding another arg to update-in, I can't think of a time when nil was actually the default value I wanted there, though sometimes the function I was using behaved well with nils (e.g., conj). In every other case, I had to explicitly handle nils (e.g., inc). I don't have a lot of production code that would need retrofitting, so I'm inclined to prefer breaking things for the better (at least while things are young). I imagine others might feel differently. On Dec 10, 7:27 am, Sean Devlin <francoisdev...@gmail.com> wrote: > 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