Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)
On Wednesday 10 December 2008 10:40, Daniel Eklund wrote: Hi all, ... One thing I immediately ran up against were certain situations where I have a map and want to modify a value several levels deep into the hierarchy. Imagine the following structure: (def nested-structure { :level 0, :nested1 { :level 1, :nested2 { :level 2, :final-data initial data}}}) Look into clojure.zip (.../src/clj/clojure/zip.clj in the Clojure source). ... 1) Am I missing something from the API that could have done what my function path-rebind? (I would have assumed that this would be a common need and that programmers would not need to roll their own each time) Yes. The Zipper. 2) Am I missing out on a clever reduce usage that could have made this more in-line? i.e. how's my code? It was after I made wrote this function and contemplated how I could make it abstract (i.e. with vectors, lists, etc) that I noticed the existence of the zip library... Maybe question 1) above is answered by the zip library. Is/Will the zip library be the recommended means by which to navigate/modify data structures of arbitrary depth, branching, and concrete 'type' ? There you have it. I would say yes. daniel Randall Schulz --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)
On Wed, Dec 10, 2008 at 1:40 PM, Daniel Eklund [EMAIL PROTECTED] wrote: user (path-rebind nested-structure [:nested1 :nested2 :final-data] new data) {:nested1 {:nested2 {:final-data new data, :level 2}, :level 1}, :level 0} Congratulations, you've implemented 'assoc-in' :-) user= (assoc-in nested-structure [:nested1 :nested2 :final-data] new data) {:nested1 {:nested2 {:level 2, :final-data new data}, :level 1}, :level 0} There are also 'get-in' and 'update-in'. Your code looks fine -- nearly identical to 'assoc-in' in fact. It does the destructuring right in the function arguments, but everything else is merely stylistic differences. --Chouser --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)
One thing I immediately ran up against were certain situations where I have a map and want to modify a value several levels deep into the hierarchy. Imagine the following structure: (def nested-structure { :level 0, :nested1 { :level 1, :nested2 { :level 2, :final-data initial data}}}) Look into clojure.zip (.../src/clj/clojure/zip.clj in the Clojure source). Excellent... thanks for the pointer. I will take a stab at using this for maps (I see stuff for vector-zip, but not yet maps). As an off-hand comment made without careful reading, I can imagine there being great utility in a special reader-syntax for paths. XSLT embeds xpath, and groovy embeds gpath. I am unsure at this point the exact capabilities of the zipper, so I don't know whether it's meant to go to a single location in a tree (it seems this way) or whether it refers to a sequence of all tree nodes that satisfy the predicates of the path (as xpath and gpath do). For the latter scenario, though, a reader syntax for a path could be very useful. thanks again ! daniel --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)
user (path-rebind nested-structure [:nested1 :nested2 :final-data] new data) {:nested1 {:nested2 {:final-data new data, :level 2}, :level 1}, :level 0} Congratulations, you've implemented 'assoc-in' :-) user= (assoc-in nested-structure [:nested1 :nested2 :final-data] new data) {:nested1 {:nested2 {:level 2, :final-data new data}, :level 1}, :level 0} There are also 'get-in' and 'update-in'. Your code looks fine -- nearly identical to 'assoc-in' in fact. It does the destructuring right in the function arguments, but everything else is merely stylistic differences. --Chouser ahh even better... I knew someone must have done this before and it kills me now to look at the API and see it right underneath the (assoc) description. I have no idea how I missed it. thanks, daniel --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)
On Wed, Dec 10, 2008 at 2:13 PM, Daniel Eklund [EMAIL PROTECTED] wrote: As an off-hand comment made without careful reading, I can imagine there being great utility in a special reader-syntax for paths. XSLT embeds xpath, and groovy embeds gpath. I am unsure at this point the exact capabilities of the zipper, so I don't know whether it's meant to go to a single location in a tree (it seems this way) That's right. Every navigation operation on a zip tree gives you a single tree with a new current location. or whether it refers to a sequence of all tree nodes that satisfy the predicates of the path (as xpath and gpath do). For the latter scenario, though, a reader syntax for a path could be very useful. For this, you may be interested in clojure.contrib.zip-filter. It takes a single zip tree and then applies a series of filters, each of which may increase or reduce the number of nodes that match (so far), and/or map each node to some new object. It has a specialization for XML zip-trees that allows expressions like: (xml- atom1 :entry :author :name text) ...where atom1 is an xml-zip tree of an atom feed. The above expression would return a seq of author name strings. It doesn't require reader macros or even regular macros. The 'xml-' function just takes a number of functions that it applies in order. The keywords are a special case for XML and act as if you wrote: (xml- atom1 (tag= :entry) (tag= :author) (tag= :name) text) A primary benefit of not having a special syntax is that it's easy to drop in custom filtering and mapping functions. For example, get the titles of atom entries with odd-numbered ids: (xml- atom1 :entry [:id text #(odd? (Integer. %))] :title text) --Chouser --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---