…semantic equality between custom created objects and predefined options.
Rationale
It might be tempting to define these types as enum for predefined options due to its succinct syntax. However, the existence of .custom(value) options challenges the use of enum.
We design every case in the enum to be unique and mutually exclusive with other cases. In the current code, multiple representations using more than one case with the same semantic can exist, violating the principle.
For example, ChordProgression.i_v_vi_iv != ChordProgression.custom([.i, .v, .vi, .iv]) but they are semantically the same. An author can write I-V-VI-IV progressions in both ways and treat them as the same. However when determining equality between I-V-VI-IV representations, we may get either true or false depending if the same representations are being compared. This is undesirable.
With minimum API change I changed the enum types to struct and make every case a static let, so ChordProgression.i_v_vi_iv == ChordProgression.init([.i, .v, .vi, .iv]). This also eliminate the separate implementation of description and combine the initializer with the declaration (so we don't need patterns like public var intervals: [Interval] { switch(self} { ... } }).
This change should be transparent to the outside API except the typo correction of Romanian Minor.
…semantic equality between custom created objects and predefined options.
Rationale
It might be tempting to define these types as
enum
for predefined options due to its succinct syntax. However, the existence of.custom(value)
options challenges the use ofenum
.We design every case in the enum to be unique and mutually exclusive with other cases. In the current code, multiple representations using more than one case with the same semantic can exist, violating the principle.
For example,
ChordProgression.i_v_vi_iv != ChordProgression.custom([.i, .v, .vi, .iv])
but they are semantically the same. An author can write I-V-VI-IV progressions in both ways and treat them as the same. However when determining equality between I-V-VI-IV representations, we may get either true or false depending if the same representations are being compared. This is undesirable.With minimum API change I changed the
enum
types tostruct
and make every case astatic let
, soChordProgression.i_v_vi_iv == ChordProgression.init([.i, .v, .vi, .iv])
. This also eliminate the separate implementation ofdescription
and combine the initializer with the declaration (so we don't need patterns likepublic var intervals: [Interval] { switch(self} { ... } }
).This change should be transparent to the outside API except the typo correction of
Romanian Minor
.