I'd like to discuss a processing of nonexhaustive external enums(imported from separate module/framework) a little more.

I understand that we (in most cases) don't want to exhaustively check some C's declared enum which is used for some system's API etc.
But what about 'usual' libraries distributed as framework/module?

Do you agree that:

1. In most cases external enums(public enums declared in *separate module*) will be nonexhaustive, because library developer don't want to crash consumer's code if later will be decided that one more enum case is needed in that public enum. Enums like Optional<T>, that should be exhaustive, will be rare in compare to "usual" enums like ButtonType, PaymentMethod, LoginKind etc

2. So, almost any enum coming from separate module/framework, even if library designer *wants* user's code to process that enum exhaustive(and it is perfectly logically to process it exhaustively in some places of user's code), will be declared as 'nonexhaustive' *just* to preserve binary compatibility if new case will be added.

3. So we actually will lose a compiler's help to work with most of such 
external enums.

4. If you ever need to support a code with exhaustive switch regarding external 'nonexhaustive' enum(and as noted above, most of such enums will be nonexhaustive) - you are in a big trouble, you'll need to manually check for each newer version of used library(module) if there are new cases in used enums for each switch in your code, or try to find a 3rd party tools that will help with this. But given you have 'default' in your switch - how the tool can say that you want tot be exhaustive here?

?

Also, please consider the two examples below. Is there incorrect logic/assumption used in any of them?

1. Let's say I have a Shapes enum in my library, which is distributes as separate module/framework. Each shape will have its own properties(like radius for .circle, side length for .square, angle and lengths for .line etc). Will I defined it as 'exhaustive' ? No. It is very possible, that I'll add some cases into the enum and I don't want to break user's code. Is it possible that user's code want to switch exhaustive on this enum? Of course, but there is no support for this in compiler. Can user's code work with new(future) enums? It depends, but *this is possible*, for example it can process only known cases, and show some warning like "unknown items found, please update to latest version of app" instead of crash.

2.
* I'm using a framework(separate module) that exports Things enum.
* This framework provides user's code with [Things] array
* I show each 'thing'(let's say its 'title' property) from that array in TableView per row * By selecting a row, I show a details page for selected thing. Information on details page depends on associated value for the selected 'thing' * For unsupported(future) 'things' I'll show only title for it in TableView and 'Unsupported' marker. Details page will not be available for it, until I update the program. When selecting it, alert will show something like "Unknown type of thing. Please update the app to support new things". * Is it required for me to be able to exhaustive switch of such enum? Yes, I need this to process all known cases in Details page. Exactly why we need exhaustive switch for 'internal' enums. But no compiler's help in this case.

I just want to say, if I understand correctly, that enum declared in separate module/framework will usually be 'nonexhaustive' even if library developer expects user's code to exhaustive switch on that enum. And that we really need a way to be exhaustive in switch in our code regarding imported enum which is declared as 'nonexhaustive' in its module.

Thank you for attention and your time.
Vladimir.

On 18.09.2017 20:23, Jordan Rose via swift-evolution wrote:


On Sep 16, 2017, at 15:35, Kenny Leung via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

In general, I agree with everything in the proposal.

I’d like to propose these alternative extensions for clients:

1) As a client of an enum, I’d like to know in the future when a new value has been added to an enum, since I may have to do something about it. How about adding the “exhaustive” keyword to be used in the switch statement? Like

exhaustive switch excuse {
    case eatenByPet:
        // …
    case thoughtItWasDueNextWeek:
        // …
    default:
        // …
}

If exhaustive is used, there would be a warning if all cases aren’t covered *even though default exists*. This means that I as the client thought I had everything covered when I wrote this code.

As already mentioned, this makes the default case un-testable, which brings me 
to

2) All non-exhaustive enums should have the pseudo value “default” that can be used just like a regular value. This would allow you to write code like:

teacher.failedToHandInHomework(excuse: .default)

which would allow you to trip the default case in any code you may write.

Brent came up with this idea as well, but after thinking it through Joe Groff and I found that it doesn't really work in practice:

It’s going to be very common to have a future value and hand it right back to the framework without looking at it, for example:

    override func process(_ transaction: @testable Transaction) {
      switch transaction {
      case .deposit(let amount):
        // …
      case .withdrawal(let amount):
        // …
      default:
        super.process(transaction) // hmm…
      }
    }


So just making it to the ‘default’ case doesn’t guarantee that it’s testable in practice.

I'll add the actual code here to the "Testing invalid cases" section under "Alternatives considered", since that's a clearer example than the paragraph I wrote. (Oh, and the "exhaustive switch" is equivalent to the section on "'future' cases".)

Thanks for the feedback!
Jordan


_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to