[swift-evolution] ValueEnumerable protocol with derived implementation for enums

Jacob Bandes-Storch jtbandes at gmail.com
Fri Apr 15 21:00:01 CDT 2016


This discussion is about a proposal for API to enumerate/count all possible
values of a type, particularly enums. The goal is to address potential
issues with an old proposal, so it can go up for review soon.

Core Team / Standard Library Team feedback would be particularly welcome
here, because we want this feature to mesh well with the goals & future
directions that are already in mind for Swift. If any details the core team
would like to see are missing from the proposal, please let us know now.

Background reading:

    • 2015-12-08: "List of all Enum values (for simple enums)" —
http://thread.gmane.org/gmane.comp.lang.swift.evolution/10064
    • 2015-12-21: "Proposal: Enum 'count' functionality"
http://thread.gmane.org/gmane.comp.lang.swift.evolution/644
    • 2016-01-17: "Draft Proposal: count property for enum types"
http://thread.gmane.org/gmane.comp.lang.swift.evolution/3678
    • 2016-01-18: "Pre-proposal: CaseEnumerable protocol (derived collection
of enum cases)" at
http://thread.gmane.org/gmane.comp.lang.swift.evolution/3701
    • 2016-01-20: My subsequent proposal PR #114:
https://github.com/apple/swift-evolution/pull/114

A lot has happened since then:

    • 2016-03-03: "[Manifesto] Completing Generics"
http://thread.gmane.org/gmane.comp.lang.swift.evolution/8484
    • 2016-03-03: "[Accepted with modifications] SE-0023 API Design
Guidelines" http://thread.gmane.org/gmane.comp.lang.swift.evolution/8585 &
http://apple.github.io/swift-internals/api-design-guidelines/
    • 2016-03-09: Brent's proposal PR #199:
https://github.com/apple/swift-evolution/pull/199

Brent brought up some great points in his proposal, but ultimately closed
the PR in anticipation of further discussion. I'm sorry I haven't had much
time to put into this until now, but I'd like us to get the discussion
going again.

I believe the community is in agreement about the following:

    • The "allValues" behavior should be provided by conformance to some
protocol, named ValueEnumerable or ValuesEnumerable or similar.
    • The compiler should derive an allValues implementation for "simple"
enums (those without associated values).

There are a couple things which we must still decide:

*### Should the ValueEnumerable protocol expose the allValues property, or
should it be an empty protocol like ErrorType (ErrorProtocol)? If exposed,
what is its type?*

If allValues were exposed as part of the protocol, then the generic
constraint <T: ValueEnumerable> could be used meaningfully, i.e. you could
write/use "T.allValues".

On the other hand, the limitations of the current generics system don't
allow "*associatedtype ValueCollection: Collection where
ValueCollection.Iterator.Element == Self*". Doug's *Completing
Generics* manifesto
included "*Arbitrary requirements in protocols*", under the category of
"Minor extensions", which would remove this limitation. If this gets
implemented, I think it makes a lot of sense to use it here.

Until then, though, we'd have to pick a concrete type for the collection.
Brent proposed that it be an Array, "static var allValues: [Self]".

The biggest reason I didn't expose allValues on the protocol was that I
figured we'd want to allow for efficient implementations which wouldn't
require allocating storage for *all* the values (just the endpoints, for
instance), but could still count and iterate over them.

Another question on the subject of exposing the property as a protocol
requirement: What should the diagnostics look like if it's missing? Maybe
something like this:

    struct MyType: ValueEnumerable { }
    // error: type 'MyType' does not conform to protocol 'ValueEnumerable'
    // note: protocol requires property 'allValues' with type '[MyType]'
    // *note: implementation of allValues cannot be automatically derived
for a non-enum type*

*### Should allValues implementations be derived for Comparable enums? What
if the sorted order does/doesn't match the source order?*

Brent has suggested the semantics of allValues should be such that for
Comparable types, allValues is guaranteed to be ordered. If that were the
case, we might not want to require the compiler to derive a ValueEnumerable
implementation, since the source order may not match the Comparable-sorted
order, and verifying this could overly complicate things. (I think I'm in
agreement here: having the values be ordered is a good implementation of
the principle of least surprise.)


Thoughts welcome.

Jacob
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160415/c5e108f8/attachment.html>


More information about the swift-evolution mailing list