This is tricky! :P I really appreciate your hard work on this crate!
In
, the default chord is erroneously missing its intervals.
The easiest way to fix this is to use ::new and call it a day, but imo that keeps the design open for a similar problem happening elsewhere.
Another viable approach:
What if we make Chord a trait instead, and make several concrete representations for it?
For example a vector of intervals could be considered a chord, albeit without a root pitch class. Chord quality and whether it's a triad/seventh /something exotic could be inferred from the intervals.
We could still construct chords from quality, string, etc but my point is we should ideally only represent it with one unique and flexible data point, because right now it's possible for the Chord struct to contain invalid data, where the fields mismatch each other and go out of sync.
If we consider performance, I'd personally vouch for being able to compute each thing from each other thing, e.g. string representation from intervals, quality from string, etc.
What do you think?