[swift-evolution] [Pitch] Use enums as enum underlying types
Dennis Lysenko
dennis.s.lysenko at gmail.com
Fri Dec 18 13:03:20 CST 2015
Sean, it would, but then we get into the whole "Well, this throws
ChangePictureError, which could be a NetworkException, or a ParseException"
thing...sound at all familiar? "Well, this throws IOException, which could
be FileNotFoundException, MalformedURLException, ProtocolException,
ObjectStreamException, UnsupportedEncodingException, SSLException...". I
guess I am just saying there is still some work to be done with regards to
wrapping and rethrowing exceptions.
How would you catch a Parse with statusCode==401 in a catch statement?
On Fri, Dec 18, 2015 at 1:49 PM Sean Heber <sean at fifthace.com> wrote:
> I may just not be understanding what this is trying to solve, but the
> following would work too, wouldn’t it?
>
> enum NetworkException {
> case NoInternetError, SecurityError
> }
>
> enum ParseException {
> case FailedResponse(statusCode: Int)
> case EmptyResponse
> case MissingField(fieldName: String)
> }
>
> enum ChangePictureError {
> case Network(NetworkException)
> case Parse(ParseException)
> etc..
> }
>
> l8r
> Sean
>
>
> > On Dec 18, 2015, at 12:42 PM, T.J. Usiyan via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > I think that you can accomplish this right now if you make your backing
> enum literal convertible. String literal would have been the better choice
> in the example below but I was feeling lazy.
> >
> > public enum MyLibError: ErrorType, IntegerLiteralConvertible {
> > case FileNotFound
> > case UnexpectedEOF
> > case PermissionDenied
> > // ... 300 cases later
> > case FluxCapacitorFailure
> > case SplineReticulationError
> > case UnknownError
> >
> > public init(integerLiteral value: Int) {
> > switch value {
> > case 0:
> > self = .FileNotFound
> > case 1:
> > self = .UnexpectedEOF
> > case 2:
> > self = .PermissionDenied
> > case 3:
> > self = .FluxCapacitorFailure
> > case 4:
> > self = .SplineReticulationError
> > default:
> > self = .UnknownError
> > }
> > }
> > }
> >
> > enum FileSystemError: MyLibError {
> > case FileNotFound = 0
> > case UnexpectedEOF = 1
> > case PermissionDenied = 2
> > }
> >
> > On Fri, Dec 18, 2015 at 12:34 PM, Dennis Lysenko via swift-evolution <
> swift-evolution at 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
> > }
> >
> > 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.lysenko at 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 at 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 at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> >
> > _______________________________________________
> > 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/20151218/1bb9e03b/attachment.html>
More information about the swift-evolution
mailing list