I'm biased as the pitcher, but I find that an "inheritance" model would be more 
straightforward than an inclusive model.

If I understand you correctly, with this model:

> enum NetworkException {
>   case NoInternetError, SecurityError
> }
> 
> enum ChangePictureError {
>   case NetworkException(NetworkException)
>   case ParseException(ParseException)
>   case PictureTooLarge
> }

you're saying that we should be able to write:

> let x: ChangePictureError = NetworkException.NoInternetError

The implicit conversion from NetworkException to ChangePictureError reminds me 
of C++ implicit constructors, which are generally frowned upon, so I'm not sure 
that this is the best way forward.

On the other hand, going back to my original example:

> enum MyLibError: ErrorType {
>       case FileNotFound
>       case UnexpectedEOF
>       case PermissionDenied
>       // ... 300 cases later
>       case FluxCapacitorFailure
>       case SplineReticulationError
> }
> 
> enum FileSystemError: MyLibError {
>       case FileNotFound = .FileNotFound
>       case UnexpectedEOF = .UnexpectedEOF
>       case PermissionDenied = .PermissionDenied
> }


I can easily rationalize that FileSystemError is implicitly convertible to 
MyLibError because of the "inheritance" relationship.

Félix

> Le 19 déc. 2015 à 14:28:44, Matthew Johnson <matt...@anandabits.com> a écrit :
> 
>> 
>> On Dec 18, 2015, at 11:34 AM, Dennis Lysenko via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> Sorry, I got a bit too excited and skimmed over the most important part of 
>> the idea. So this is a special type of enum declaration in which you cannot 
>> declare any new enum members. I personally have not seen a use for this in 
>> my code but I would love to hear others' response to it. It is a very 
>> interesting idea though.
>> 
>> I'm going to go out on a limb with an idea that is in the same vein as this 
>> one: What if we favored composition over inheritance here, and made it so 
>> that you could transparently refer to members of other enums *without* 
>> having another enum as a backing type?
>> 
>> e.g., you have:
>> enum NetworkException {
>>   case NoInternetError, SecurityError
>> }
>> 
>> enum ParseException {
>>   case FailedResponse(statusCode: Int)
>>   case EmptyResponse
>>   case MissingField(fieldName: String)
>> }
>> 
>> As two general classes of errors. But for a full API call wrapper, you might 
>> want an error class that composes the two, so that when calling the API call 
>> from your UI code, you can display a "please check your connection" message 
>> for NoInternetError, a "Please log in" error for FailedResponse with 
>> statusCode=401, or a "server error" message for any of the rest. 
>> 
>> I wonder how do you and others feel about that use-case? I have certainly 
>> seen it come up a lot in real-world projects that require resilient UI 
>> interactions with nontrivial networking operations.
>> 
>> Here are some quick code samples off the top of my head for how we might go 
>> about this (let's say the API operation is "change profile picture":
>> 
>> enum ChangePictureError {
>>   include NetworkException
>>   include ParseException
>>   case PictureTooLarge
>> }
> 
> By including all of the cases you make it possible for ChangePictureError to 
> be a supertype of NetworkException and ParseException.  This is a pretty 
> interesting idea.  It might be worth exploring.  
> 
> One thing that would need to be considered is that ideally if the actual 
> values was a NetworkException case you would want to be able to call any 
> methods exposed by Network Exception.  A good way to accomplish that might be 
> to add implicit conversion as well as syntactic sugar for nested enums.  So 
> if we have this:
> 
> enum ChangePictureError {
>   case NetworkException(NetworkException)
>   case ParseException(ParseException)
>   case PictureTooLarge
> }
> 
> I can do this:
> 
> var error: ChangePictureError // set somewhere, can be set with a 
> NetworkException or a PictureTooLarge
> switch error {
> case .NoNetworkError:                           // equivaluent to case 
> .NetworkException(.NoNetworkError)
> case .NoInternetError:                            // equivaluent to case 
> .NetworkException(. NoInternetError)
> case .FailedResponse(let statusCode): // equivaluent to case 
> .ParseException(.FailedResponse(let statusCode))
> case .EmptyResponse:                          // equivaluent to case 
> .ParseException(.EmptyResponse)
> case .MissingField(let fieldName):         // equivaluent to case 
> .ParseException(. MissingField(let fieldName))
> case .PictureTooLarge:
> }
> 
> The syntactic sugar would only work for case names where there is no overlap. 
>  Case names that overlap would need to be explicitly disambiguated.  The 
> syntactic sugar and implicit conversions could allow for either single-level 
> nesting or arbitrary nesting depth.  An example of arbitrary depth might be 
> ParseException also containing a ValidationError case:
> 
> enum ValidationError {
>   case OutOfRange
>   case InvalidType
> }
> 
> enum ParseException {
>   case ValidationError(ValidationError)
>   case FailedResponse(statusCode: Int)
>   case EmptyResponse
>   case MissingField(fieldName: String)
> }
> 
> Mostly just thinking out loud here and exploring the idea.  What do others 
> think of this?
> 
>> 
>> or
>> 
>> enum ChangePictureError {
>>   compose NetworkException.NoInternetError
>>   compose ParseException.EmptyResponse
>>   compose ParseException.FailedResponse(statusCode: Int)
>>   case PictureTooLarge
>> }
>> 
>> Not a proposal by any stretch of the imagination, just a potential direction 
>> inspired by your idea, Felix.
>> 
>> 
>> On Fri, Dec 18, 2015 at 12:21 PM Dennis Lysenko <dennis.s.lyse...@gmail.com 
>> <mailto:dennis.s.lyse...@gmail.com>> wrote:
>> Felix, 
>> 
>> This seems to be very interestingly tied into your comments about 
>> polymorphism in 'throws' type annotations. Would you not feel that allowing 
>> enums to be built on top of other enums would promote the kind of egregious 
>> proliferation of exception polymorphism that discourages so many from 
>> following Java's checked exception model? 
>> 
>> On Fri, Dec 18, 2015 at 11:29 AM Félix Cloutier <swift-evolution@swift.org 
>> <mailto:swift-evolution@swift.org>> wrote:
>> Hi all,
>> 
>> Swift currently has more or less three conceptual types of enums: 
>> discriminated unions, lists of unique tokens, and lists of value of a raw 
>> type.
>> 
>> > // Discriminated unions
>> > enum Foo {
>> >       case Bar(Int)
>> >       case Baz(String)
>> > }
>> >
>> > // Lists of unique tokens (mixable with discriminated unions)
>> > enum Foo {
>> >       case Frob
>> >       case Nicate
>> > }
>> >
>> > // Lists of raw values
>> > enum Foo: String {
>> >       case Bar = "Bar"
>> >       case Baz = "Baz"
>> > }
>> 
>> I think that the last case could be made more interesting if you could use 
>> more types as underlying types. For instance, it could probably be extended 
>> to support another enum as the backing type. One possible use case would be 
>> to have a big fat enum for all the possible errors that your program/library 
>> can throw, but refine that list into a shorter enum for functions that don't 
>> need it all.
>> 
>> > enum MyLibError: ErrorType {
>> >       case FileNotFound
>> >       case UnexpectedEOF
>> >       case PermissionDenied
>> >       // ... 300 cases later
>> >       case FluxCapacitorFailure
>> >       case SplineReticulationError
>> > }
>> >
>> > enum FileSystemError: MyLibError {
>> >       case FileNotFound = .FileNotFound
>> >       case UnexpectedEOF = .UnexpectedEOF
>> >       case PermissionDenied = .PermissionDenied
>> > }
>> 
>> This example could be made simpler if the `= .Foo` part was inferred from 
>> the name, but you get the idea.
>> 
>> In this case, it would be helpful (but not required) that FileSystemError 
>> was convertible into a MyLibError, so that it could be transparently 
>> rethrown in a function that uses the larger enum. I personally don't see why 
>> enums with a specified underlying type can't be implicitly converted to it, 
>> but this is not currently the case and it probably deserves some discussion 
>> as well.
>> 
>> Is there any interest in that?
>> 
>> Félix
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>  _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <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