Despite what others have said, I'm going to chime in and say that I think an immutable hierarchy is going to be awkward for the use case you describe.
In your example, notes are buried fairly deep in a hierarchy. Now if you always tend to make manipulations by starting from the root score node and working your way down the hierarchy, immutability works just fine. But if you want to modify a note that somehow you've stored in a separate list of notes, or the user has clicked on the note, or some other kind of interaction where the note is being considered separately from the rest of the hierarchy, you've got a problem. update-in and assoc-in are only useful if you know the route from the root score node to the note. And that information might not be readily available. Similarly, the zipper library is only useful if you've arrived at a given note through a series of zipper-style navigations down the hierarchy. So I really doubt that either of these proposed solutions will do you much good if you need to frequently manipulate notes without drilling down to get to them. I think you have two basic options: 1. Use refs. A score/measure/note/etc. are each refs containing the appropriate struct. This is basically like using pointers in a typical language, but you have the advantage of using transactions to make a bunch of simultaneous updates where other threads will never see the tree in an intermediate state. 2. Each struct for score/measure/note also contains a "name" field which contains a unique name. Maintain a big map of all names to structs. Scores do not directly link to measures, but instead contain the *names* of the measures. To drill down from a score to the measure, you must look up the measure by name in the big map. To update a note, you just assoc the note name with the new note object in the big map. This method is fully immutable. Updating a note without knowing the full route through the hierarchy is easy because the objects are not directly coupled. The big map of names to structs is a persistent object that essentially can give you a snapshot history of all changes that are made. The main price you pay is that drilling down through the hierarchy becomes a bit slower because you must always look up the names in the map. -- 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