This seems like a reasonable optimization. I read something similar a few years ago (http://lorgonblog.wordpress.com/2008/05/24/catamorphisms-part-four/):
What we want is a function which will be smart, and only allocate new data structures when necessary. Indeed, one of the main advantages of immutable data structures is the ability to "share" portions of structure. Bobby On Monday, February 24, 2014 4:00:34 PM UTC-5, Brian Craft wrote: > > This is vaguely related to David's posts about om/react, where he talks > about optimizing state change tracking by checking object identity on > immutable objects: deep compares can be avoided if same identity implies no > changes. > > My first thought was that there are many algorithms that will give you a > new object every time, even if nothing has changed. E.g. if your state has > an array whose elements must be validated, doing a map over the elements > will give you a new array every time, even if it makes no changes. > > Enforcing non-negative values, for instance: > > => (let [x {:a [1 -2 3]}] (update-in x [:a] (fn [y] (mapv #(if (< % 0) 0 > %) y)))) > {:a [1 0 3]} > > In the following case the values are already non-negative, but we still > get a new object: > > => (let [x {:a [1 2 3]}] (identical? x (update-in x [:a] (fn [y] (mapv > #(if (< % 0) 0 %) y))))) > false > > One can imagine trying to rewrite this so it passes through the vector if > nothing has changed. E.g. > > => (let [x {:a [1 2 3]}] (identical? x (update-in x [:a] (fn [y] (reduce > (fn [v i] (if (< (v i) 0) (assoc v i 0) v)) y (range (count y))))))) > true > > => (let [x {:a [1 -1 3]}] (identical? x (update-in x [:a] (fn [y] (reduce > (fn [v i] (if (< (v i) 0) (assoc v i 0) v)) y (range (count y))))))) > false > > I expect many algorithms would need to be reworked like this in order to > rely on object identity for change tracking. Is this madness? Am I thinking > about this the wrong way? > > > An interesting note here is that the next-to-last update-in, above, > returned the same object. I didn't know update-in could return the same > object. A simpler example: > > => (let [x {"a" [1 2 3]} y (update-in x ["a"] (fn [z] z))] [x y > (identical? x y)]) > [{"a" [1 2 3]} {"a" [1 2 3]} true] > > => (let [x {"a" [1 2 3]} y (update-in x ["a"] (fn [z] [1 2 3]))] [x y > (identical? x y)]) > [{"a" [1 2 3]} {"a" [1 2 3]} false] > > > Is this some kind of optimization in update-in, that it doesn't create a > new object if the new attribute is identical to the old attribute? Is it > peculiar to the data type? Is it documented anywhere? > > > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.