Hello, On Mon, Dec 21, 2009 at 11:09 PM, PM <peter.mccull...@gmail.com> wrote: > I'm a new Clojure user. I've been working my way through SICP and the > videos that accompany it, and I've also read the Clojure book. I > already do a lot of work with a music notation library (JMSL) in Java, > and I'd like to see if I could do some tasks more simply in Clojure. > > One of the issues I run into is how to represent a musical score using > immutable objects. A naïve representation of a score might look > something like: > > - Score contains measures > - Measures contain staves > - Staves contain tracks > - Tracks contain notes > - Notes contain articulations, dynamics, and other extras. > > I've mocked it up before using structmaps, but I get stuck when it > comes to doing all this with immutable structures. Immutability is no > problem for a system like Lilypond where the score data is fixed when > the program runs, but in a system where some of these items may be > changing as the score is edited, how do you handle that? Returning a > new note via assoc implies that a track's contents would also change, > making it a new track, and so on up the chain. (?)
Are you worried about data structure copying? Because I think you shouldn't be. Clojure's persistent data structure minimize copying, and besides, even in older languages this kind of update has a 'functional flavor'. For instance, in K&R's "The C Programming Language", 1st edition, there is an example about counting words which uses a binary tree to ensure quick access to a word. So this is C, imperative, with manual memory management. But what they do is reuse subtrees a lot (If one has to add a word to a tree, it's either added to the left or the right subtree, and the unmodified subtree is just reused - this means that, barring unbalancing of the tree, when modifying a tree with N elements, they actually only change/rebuild Log2(N) nodes, and the rest is reused). The same happens a lot with data structures in functional languages - the simplest example being consing, which creates a new list from an old list, but it's all a O(1) operation because the old list is just reused/linked to. With nested maps in Clojure it's the same. If you use update-in or assoc-in to update a note, the score is mostly the same, because most of the old score is reused (even though it's a 'new one' - which makes sense). <=== so try using update-in, assoc-in and get-in and maybe your data structure will be easier to manipulate. Zippers are great too, as James Sofra suggests. I hope I managed to describe what you were missing, I probably used too many words in the attempt :-) -- Miron Brezuleanu -- 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