Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] Initializers for value-holding types #103

Closed
jsbean opened this issue Oct 4, 2019 · 6 comments · Fixed by #163
Closed

[API] Initializers for value-holding types #103

jsbean opened this issue Oct 4, 2019 · 6 comments · Fixed by #163
Milestone

Comments

@jsbean
Copy link
Member

jsbean commented Oct 4, 2019

There are many types which have properties named value, which are generally "Simple Types", and are what XMLCoder calls "Coding Key Value Intrinsic". In XML parlance, complex types "extend" "Simple Types" with attributes.

For these types, we can remove the attribute label in initializers, as these types are required and usually self-explanatory.

For example, the complex type stem "extends" the stem-value type.

I suggest we implement initializers for types like this:

extension Stem {
    init(_ value: StemValue, ...) {
        self.value = value
        ...
    }
}

Which make the call site look something like this:

let stem = Stem(.up)

@DJBen, does this work for or against any of your thoughts on the matter?

@DJBen
Copy link
Collaborator

DJBen commented Oct 4, 2019

I think this makes sense and I agree. We just want to make sure this case applies to simple types only.

@jsbean
Copy link
Member Author

jsbean commented Oct 8, 2019

I think this methodology could also be extended to types which are inherently attributed arrays of a union type (i.e., Kind) (e.g., Notations, Ornaments, Dynamics, Technical, Encoding, etc.).

Thus, we could have:

let notations = Notations([.ornaments(Ornaments([.mordent(Mordent())]))])

Instead of:

let notations = Notations(
    values: [
        .ornaments(
            Ornaments(
                values: [
                    .mordent(Mordent())
                ]
            )
        )
    ]
)

Furthermore, we could make these types conform to ArrayLiteralConvertible if they are simple cases like so (without attributes).

let notations = Notations([.ornaments([.mordent(Mordent()))])

@jsbean
Copy link
Member Author

jsbean commented Oct 8, 2019

And to really stretch the ergonomics, we may be able to get away with defining static properties on top of these union types:

extension Ornament {
    static let mordent = Ornament.mordent(Mordent())
}

Thus making the previous example:

let notations = Notations([.ornaments([.mordent])])

Not entirely certain that the compiler will appreciate this, but it could be worth a try.

@DJBen
Copy link
Collaborator

DJBen commented Oct 8, 2019

And to really stretch the ergonomics, we may be able to get away with defining static properties on top of these union types:

extension Ornament {
    static let mordent = Ornament.mordent(Mordent())
}

Thus making the previous example:

let notations = Notations([.ornaments([.mordent])])

Not entirely certain that the compiler will appreciate this, but it could be worth a try.

We can already specify default values to the enums, like

enum Ornament {
    case mordent(Mordent = Mordent())
}

@jsbean
Copy link
Member Author

jsbean commented Oct 8, 2019

Wait, whoa, what?! When did that happen? I'm gonna give that a shot.

@jsbean
Copy link
Member Author

jsbean commented Oct 8, 2019

That's wild. The only slightly noisy aspect is that it has to be called as .mordent() rather than .mordent, but that is very interesting.

@jsbean jsbean added this to the 0.4.0 milestone Oct 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants