[swift-evolution] Consolidate Code for Each Case in Enum

Tim Shadel timshadel at gmail.com
Sat Jan 14 16:33:30 CST 2017


With everything quiet on this discussion since my last update removing defaults, I've gone ahead and submitted a pull request (https://github.com/apple/swift-evolution/pull/585 <https://github.com/apple/swift-evolution/pull/585>) with the latest draft. I'm certainly happy to still update it if anything arises.

Thanks to all who helped out!

—Tim

> On Jan 13, 2017, at 12:23 AM, Rien <Rien at Balancingrock.nl> wrote:
> 
> +1
> 
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Swiftrien
> Project: http://swiftfire.nl
> 
> 
> 
> 
>> On 13 Jan 2017, at 03:01, Tim Shadel via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Fantastic points, all. Let me reply to a few.
>> 
>> First, the odd situations you mentioned with the defaults were spot on. I had seen them, and thought a bit about it, but having you write it out in code made it obvious that they're pretty harmful. I've removed defaults entirely (see the updated Alternatives and Errors sections). This is actually a really good indicator of whether you should use this syntax or not. If you'll save a noticeable amount of space by using a default, then this isn't the syntax for your situation.
>> 
>> To make that more obvious, I've added a Mixed Use Example (https://gist.github.com/timshadel/5a5a8e085a6fd591483a933e603c2562#mixed-use-example) showing how simple it is to use the existing syntax when you have a default and a small number of exceptions, alongside the case block syntax for things that are unique for each case. So, to summarize, I think that forcing the additional code for each case is a good thing so that this syntax remains the exception used when needed, instead of becoming the rule.
>> 
>> Now to your other points. The intent isn't to alter the amount of code required to accomplish the task (code *complexity*), but to simplify *maintenance and understanding* by allowing you to organize the code either by property or by case (according to the merits of the code and your judgement). Indeed, I try to highlight in the proposal that this usually _increases_ code verbosity slightly in favor of the readability gained by shifting the code layout.
>> 
>> Finally, to your point about attaching properties to values (also echoed in David's musings about tagged unions vs Swift enums), it is different, but I'm not sure of a cleaner way to group all the code related to a single case for complex enums. In another light, no other type in Swift makes such heavy use of `switch` statements as a mechanism to organize code, and so this starts to make enum code look more like the rest of the code you find in Swift projects, which could be a good thing for long-term readability.
>> 
>> 
>>> On Jan 11, 2017, at 9:22 AM, Tony Allevato <tony.allevato at gmail.com> wrote:
>>> 
>>> I'll summarize my thoughts for now, after thinking about it for a bit longer:
>>> 
>>> Plusses:
>>> + In some cases it's nicer to have the ability to group functionality at each case rather than spread across methods lower in the type definition. I've written enums that were like state machines where being able to have the next state transition and other associated data grouped with the case would have made the code a bit cleaner, IMO.
>>> + This is the cleanest syntax I've seen proposed for this idea.
>>> 
>>> Things that worry me:
>>> – It's a new way to express the same idea without necessarily *simplifying* it in terms of code complexity.
>>> – It adds a fair amount of complexity to the compiler, to build the implicit self-switch and merge the implementations for each partial property/function.
>>> – It would be the first time, I believe, in Swift where properties/method implementations are attached to *values* rather than just to the *type*. That's quite a departure from the way we model these concepts.
>>> – The use of the type-defined implementation as the default when a case-defined implementation is omitted can lead to some bizarre combinations, which I think need to be addressed in the proposal. Consider this:
>>> 
>>> ```
>>> enum Foo {
>>>  var description: String {
>>>    switch self {
>>>    case .bar: return "bar"
>>>    case .baz: return "baz"
>>>    default: return ""
>>>  }
>>> 
>>>  case bar
>>>  case baz
>>>  case quux {
>>>    var description: String { return "quux" }
>>>  }
>>> }
>>> ```
>>> 
>>> Should the user be able to omit the `default` case because everything is exhaustively covered without it? *Conceptually* yes, but that would require the compiler to analyze the switch statement inside `description` and understand that, which is probably not feasible for anything but the simplest examples (and perhaps not even for those). Otherwise, it would presumably transform the implementation to this:
>>> 
>>> ```
>>>  var description: String {
>>>    switch self {
>>>    case .quux: return "quux"
>>>    default:
>>>      switch self {
>>>      case .bar: return "bar"
>>>      case .baz: return "baz"
>>>      default: return ""
>>>    }
>>>  }
>>> ```
>>> 
>>> ...which produces the expected output, but the generated code might not be ideal.
>>> 
>>> That makes me question whether we should allow default implementations at all. If we didn't allow it, we potentially require the user to write *more* code because they would have to duplicate the defaults under each case separately. But it opens a door to potential confusion if we do allow them.
>>> 
>>> So... I guess I'm on the fence right now. I want to support this from the point of view that syntactically it would improve the quality of some of the enums I've written, but I'm hedging a bit conservatively because of those concerns above.
>>> 
>>> 
>>> On Wed, Jan 11, 2017 at 7:08 AM David Sweeris <davesweeris at mac.com> wrote:
>>> 
>>> On Jan 11, 2017, at 08:48, Derrick Ho via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>>> Interesting proposal Tim. So instead of repeating the enum cases multiple times we repeat the functions multiple times?
>>>> 
>>>> I feel like this merely flipping the complexity but not really getting rid of it.
>>> 
>>> I think you have correctly summarized the proposal.
>>> 
>>> The complexity can't be gotten rid of (except maybe with macros... depending on the details, of course). Sometimes viewing the same thing from a different angle can be helpful. As long as this syntax is "in addition to" and not "instead of", the only downside I can see to allowing this is a bit of "language bloat", which doesn't particularly bother me. I don't know how hard it would be for the compiler to sort out which "mode" it should parse the enum in, though, especially since you might want to write some parts in the regular way and some parts in this new way.
>>> 
>>> So... I guess I'm +1, pending someone who knows more about compiler internals weighing in on implementation implications.
>>> 
>>> - Dave Sweeris
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170114/6d0ec86a/attachment.html>


More information about the swift-evolution mailing list