[swift-evolution] ValueEnumerable protocol with derived implementation for enums
Vladimir.S
svabox at gmail.com
Mon Apr 25 10:31:05 CDT 2016
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)
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
More information about the swift-evolution
mailing list