[swift-evolution] [Pitch] Synthesized static enum property to iterate over cases

Kevin Nattinger swift at nattinger.net
Fri Sep 8 13:48:37 CDT 2017


I've been waiting for this for years. Literally since Swift was announced. IMO it's one of several major gaps in the language.

Some thoughts:
- It should be a simple array. 
	- By far the most simple solution, and the one I (and, I'd guess, others) would expect.
	- Every time I've needed the count, I need the actual values either within the same method or within the same run loop (e.g. table view).
	- In my experience, direct indexing into the values array is more common than iterating over it.
	- Rarely more than a few cases.
	- Even an enum with a lot of cases, the actual number is trivial compared to the program's memory usage.
	- No compiler magic beyond spitting out the static array. How do you propose to generate on-demand a sequence of values without compiler magic and without the values being stored somewhere?
- It should always be in declaration order. Period. 
	- Reordering only in the case of Int raw values (especially only when 0-N are all covered) is unintuitive at best, and I expect rarely what the dev would want.
- Should only work on enums without associated values. Enumerating on associated values is just begging for trouble. 
	- (Infinite) recursion, as you pointed out.
	- It seems more intuitive to me to have enumerated cases grouped, but what if there are cases with and without ATs?

>> [...]
>> Great points! I was only considering the table view/section case where the enum had raw values 0..<count, but I do imagine it's possible that someone could just define `enum Section { case header, content, footer }` and then want to turn an IndexPath value into the appropriate Section.
>> 
>> On the other hand, though, isn't that what raw value enums are for? If the user needs to do what you're saying—map specific integers to enum values—shouldn't they do so by giving those cases raw values and calling init?(rawValue:), not by indexing into a collection? Especially since they can already do that today, and the only thing they're missing is being able to retrieve the count, which a "PrecountedSequence" mentioned above, or something like it, could also provide.

I... guess one could do that? Seems undesirable to me. What if I have them explicitly numbered, and delete one? Oops, now the whole thing is off and I have to go fix all the numbers. Besides, what if the dev wants to use it as a different raw representable? (`enum Title: String { ... }`)?

> 
> First, I’m making observations about what people are doing, not what they could do.  
> 
> Second, the raw value may not correspond to 0-based indices.  It might not even be an Int.  There is no reason to couple this common use case of `allValues` to `Int` raw values with 0-based indices.

+1000. There is absolutely no reason to join these, or special-case 0-N int raw representables. 

> 
> Do we know of any examples where a user is both (1) defining an enum with integer raw values that are noncontiguous or non-zero-based and (2) need declaration-ordinal-based indexing into those cases for other reasons, like a table/collection view? I can't think of why someone would do that, but I'm happy to consider something that I'm missing.

Some underlying meaning? E.g. not a table view, but values or identifiers for some sort of low-level protocol.

>  
> 
> Third, `init(rawValue:)` is a failable initializer and would require a force unwrap.  If the raw values *are* 0-based integers this is similar to the collection bounds check that would be necessary, but it moves it into user code.  People don’t like writing force unwraps.
> 
> Yeah, this is a really good point that I wasn't fully considering. If other invariants in the application hold—such as table view cell functions never receiving a section index outside 0..<count—then unwrapping it just forces users to address a situation that will never actually occur unless UIKit is fundamentally broken.

Or the user makes a mistake numbering cases, or forgets to update something, ... I usually put an assertion failure there, but I hate relying on even system libraries in production code. 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170908/1a789c3d/attachment.html>


More information about the swift-evolution mailing list