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

Vladimir.S svabox at gmail.com
Tue May 24 16:16:07 CDT 2016


 > Personally, I'm fine with ValuesEnumerable being a "magic protocol" like
 > ErrorProtocol, because the most important use case is being able to write
 > e.g. `NSTextAlignment.allValues` with a compiler-provided implementation. A
 > proper associatedtype declaration can come later, once generics are mature
 > enough.

OK. Agree.

 > Your reasoning is correct. This proposal was only intended to handle the
 > "simple" case, because having a good solution for the simple case sooner,
 > rather than waiting for a *perfect* solution much later, seems like a good
 > idea to me.

Support this opinion. We can introduce such a protocol now in 3.0 and 
implementation for 'simple' enums and then (3.x or 4) extent it to 
'complex' enums.


Btw, I also think we need some .next/.prev properties for cases(i.e. var 
emotion = Emotions.sad; emotion = emotion.next // will be '.neutral', then 
`.happy`). As even with `.allValues` you need to write a code to find 
current case in that array, then return next case. But probably this could 
be introduced later.


On 24.05.2016 9:37, Jacob Bandes-Storch wrote:
> ...1 month passes...
>
> On Mon, Apr 25, 2016 at 8:31 AM, Vladimir.S via swift-evolution
> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>
>     Sorry, if was discussed earlier, tried to find in conversations in this
>     thread but didn't find:
>
>     Could someone please briefly describe why "community is in agreement" -
>     "The "allValues" behavior should be provided by conformance to some
>     protocol" ?
>     I mean, what is purpose of the protocol? What else, other than
>     allValues for enums, could be implemented with such protocol? How it
>     will be used?(Like to see a possible code sample)
>
>
> Whether the `allValues` property should be exposed as a protocol
> requirement was one of the main questions I brought up at the beginning of
> this thread.
>
> Personally, I'm fine with ValuesEnumerable being a "magic protocol" like
> ErrorProtocol, because the most important use case is being able to write
> e.g. `NSTextAlignment.allValues` with a compiler-provided implementation. A
> proper associatedtype declaration can come later, once generics are mature
> enough.
>
>
>     How I think about this feature: we have "simple" enums(.First, .Second,
>     .Third), we have enums with "raw" values(.First = 1) and we have
>     "complex" enums like
>     enum E<T> {
>         case First(Int,T)
>         case Second(SomeStruct)
>     }
>
>     What we need? We need to be able to iterate over all declared cases in
>     enum. Often we needs to pre-create some resources depending on what
>     'kind' of values(and their count) could be in enum.
>
>     Let's take this "complex" E<T> enum.
>     IMO we need to be able to have such code:
>
>     let columns = Columns(count: E<Int>.allValues.count)
>
>     for e in E<Int>.allValues {
>       switch e { // << here is a problem for complex enums, it can't return
>     actial enum value as assotiated values are not known (Int,T)/SomeStruct
>     // but there is no problem for "simple" enums to return actual value here
>
>         case .First : columns.newColumn(titled: "First", color: red)
>         case .Second : columns.newColumn(titled: "Second", color: blue)
>
>         // !!! no 'default:' here : this will protect us if E is changed
>       }
>     }
>
>     As I understand, to be able to iterate 'complex' enums we need some new
>     type related to enum. I mean what exactly are ".First" and ".Second"
>     that are specified inside 'switch'? I.e. what is placed by compiler
>     inside 'switch' as ".First" and as ".Second"? What hidden property of e
>     is compared with these ".First" and ".Second" ?
>
>     Here is the code:
>
>     var e : E<String> = .First(1, "str")
>     switch e { // e is compared in run-time
>         case .First : print("first")   // e is a concrete value of
>     'complex' enum, but we can compare just '.First' about it. So, .First
>     does not create an instance of E<String>, it is some 'special' value
>
>         case .Second : print("second")
>     }
>
>     It seems like we need some 'magic' EnumCase type and some compiler
>     changes to be able to write some kind of this:
>
>     for e in E<Int>.allCases { // e is EnumCase, we have need .allCases
>       switch e {
>
>     // here compiler allows to use our EnumCase to get a general 'kind' of
>     defined cases in enum
>     // i.e. 'e' contains the same value(and only this value) that compiler
>     internally stores in 'switch' now (in code above)
>
>         case .First : columns.newColumn(titled: "First", color: red)
>         case .Second : columns.newColumn(titled: "Second", color: blue)
>
>         // !!! no 'default' here, it is important!
>         // because of this we need compiler magic insted of checking some
>         // function like E<Int>.caseIf(from: .First) as function will require
>         // a 'default:' clause.
>       }
>     }
>
>     As for 'simple' enums - they can be iterated without such special
>     'EnumCase' type, but for consistency probably could be implemented in
>     the same way. Or for 'complex' enums we need such a special case.
>
>     As for ordering, it is clear for me that we need order items in
>     allValues exactly as defined in code. We always can have rawValue from
>     enum, but can't get enum definition order by rawValue.
>
>     Opinions?
>     Please let me know if something is incorrect in my reasoning
>
>
> Your reasoning is correct. This proposal was only intended to handle the
> "simple" case, because having a good solution for the simple case sooner,
> rather than waiting for a *perfect* solution much later, seems like a good
> idea to me.
>
>
> To me, it seems that a "magic protocol" with no public requirements,
> producing an internal (non-resilient) static array, is a reasonable
> solution that *might* be able to fit into the Swift 3 timeframe, and I
> think that'd be a huge boon to language users. I also don't think it
> precludes further improvements.
>
> Do others agree? Disagree? Is it definitely out of scope for Swift 3
> regardless of the approach we choose?


More information about the swift-evolution mailing list