Alphabet Project, Part 7
- Alphabet Project, Part 1
- Alphabet Project, Part 2
- Alphabet Project, Part 3
- Alphabet Project, Part 4
- Alphabet Project, Part 5
- Alphabet Project, Part 6
Refactoring Elixir - structuring measures
Looking at the full version 1 of the code I’ve written over the past 6 blog posts, there is a lot of refactoring to be done. A lot of it falls under the category of naming cleanup and extracting common code – especially around writing out to LilyPond files – which is all self-explanatory enough not to necessitate going into any further detail. There is one aspect of the project that I found frustrating even during the original development, but by the time I began to feel hampered by it, the drive to complete a working version was stronger than my desire to go back, so I let it slide.
But no longer. Looking through the code, the way I’ve handled structuring the measures, which in many ways are the fundamental building blocks of the score, left a bit to be desired.
In the first version of the polyrhythm generator, there was no structure at all. Instead, each measure was represented first and only by a single constructed string:
Versions 2-4 were no better. When we got to version 5, this tuple started to show up:
Now, instead of having a simple string for the measure, we have a tuple of
with which we can more easily modify the notes in the measure, since they are a list of items, rather than a string that would need to be split and parsed.
But this is still rather a cumbersome form to pass around, especially when, as happens in many cases, we want to include the index of the measure in the part:
For pattern matching, this is far from optimal, especially if we want to ignore
some of the fields or further match on the head/tail of the notes. Plus, we need
to know what each element in the form means. { { {n, d}, ns}, i}
is hardly the
most descriptive Elixir form.
Fortunately, Elixir provides structs, which will help us accomplish what we want.
With this data format, instead of needing to write code like this to attach dynamics and phonemes to the first event of a measure
we can simply set the dynamic and phoneme in the struct attributes
and push LilyPond formatting off onto the module itself:
This way, when generating the LilyPond files, all we need to call in our generators is
and we have a properly formatted LilyPond string for each measure without needing to fumble around with spacing and beaming in every generator.
The code, refactored to use this Measure
struct consistently, can be found
on Github here.
Thanks for reading! If you liked this post, and want to know when the next one is coming out, follow me on Twitter (link below)!