> On Aug 18, 2017, at 11:43 PM, Mark Lilback <m...@lilback.com> wrote:
> 
>> 
>> On Aug 18, 2017, at 2:27 AM, John McCall via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> Even for non-public code.  The only practical merit of typed throws I have 
>> ever seen someone demonstrate is that it would let them use contextual 
>> lookup in a throw or catch.  People always say "I'll be able to exhaustively 
>> switch over my errors", and then I ask them to show me where they want to do 
>> that, and they show me something that just logs the error, which of course 
>> does not require typed throws.  Every.  Single.  Time.
> 
> We're doing it in the project I'm working on. Sure, there are some places 
> where we just log the error. But the vast majority of the time, we're 
> handling them. Maybe that's because we're using reactive programming and 
> errors bubble to the top, so there's no need to write that many error 
> handlers. And if I am just logging, either the error doesn't really matter or 
> there is a TODO label reminding me to fix it at some point.

I'm not saying people only log errors instead of handling them in some more 
reasonable way.  I'm saying that logging functions are the only place I've ever 
seen someone switch over an entire error type.

I keep bringing exhaustive switches up because, as soon as you have a default 
case, it seems to me that you haven't really lost anything vs. starting from an 
opaque type like Error.

>> On Aug 18, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> The primary goal for me personally is to factor out and centralize code that 
>> categorizes an error, allowing catch sites to focus on implementing recovery 
>> instead of figuring out what went wrong.  Here’s some concrete sample code 
>> building on the example scenario above:
> 
> I'm using a similar approach. Here is some stripped down code:
> 
> //error object used throughout project
> public struct Rc2Error: LocalizedError, CustomStringConvertible, 
> CustomDebugStringConvertible {
>       /// basic categories of errors
>       public enum Rc2ErrorType: String, Error {
>               /// a requested object was not found
>               case noSuchElement
>               /// a requested operation is already in progress
>               case alreadyInProgress
>               /// problem parsing json, Freddy error is nested
>               case invalidJson
>               /// nestedError will be the NSError 
>               case cocoa 
>               /// nested error is related to the file system 
>               case file 
>               /// a wrapped error from a websocket 
>               case websocket 
>               /// a generic network error 
>               case network 
>               /// an invalid argument was passed (or parsed from json)
>               /// wraps an unknown error
>               case unknown
>       }
> 
>       /// the generic type of the error
>       public let type: Rc2ErrorType
>       /// the underlying error that caused the problem
>       public let nestedError: Error?
>       /// location in source code of where error happened
>       public let location: String
> }

Okay.  I mean, this seems essentially like Swift's Error design.  The comment 
says you use this type ubiquitously in your project.  The type completely 
erases any differences between functions in terms of what errors they can 
throw.  Predictably, it includes an unknown case.  Code that processes values 
of this type must look essentially exactly like switching over an Error, except 
that the unknown case involves explicitly matching '.unknown' instead of using 
'default'.

> //a domain-specific error type that will be nested
> public enum NetworkingError {
>       case unauthorized
>       case unsupportedFileType
>       case timeout
>       case connectionError(Error)
>       case canceled
>       case uploadFailed(Error)
>       case invalidHttpStatusCode(HTTPURLResponse)
>       case restError(code: Int, message: String)
> }

Okay.  So you're doing semantic tagging of errors — you're communicating out 
that an error arose during a specific operation.  And having some static 
enforcement here makes it easier to ensure that you've tagged all the errors.

> The most common errors don't need a nested error. The call site can figure 
> out how to recover based on this. Using Result<T,E> I can specifically limit 
> what kind of errors are possible from a function without using the wrapper 
> error. E can always be specified as Error to ignore the typed system.

I see.  So you do have some functions that use a more specific type.

> It would be great if the native swift error system let you optionally put 
> compiler-enforced constraints on what kind of error can be thrown. Then I can 
> setup handlers for my specific type of error, but the compiler will give an 
> error/warning if I'm not handling a possible Error. A generic catch-all is 
> not proper error handling.

Do you really check for eight different cases at the call sites that get a 
NetworkingError, or is there a common predicate that you use?  Is there a 
reason that predicate cannot be written on Error?

> And if I'm calling something that doesn't throw type-constrained errors, I 
> can use a generic handler and wrap it up in my own error. But the call site 
> is getting details necessary to recover (if possible) without having to use 
> the runtime to figure out what kind of error it is.

Can you talk about about why "without using the runtime" is an important 
requirement to you?  Why is an enum-switch with a catch-all case acceptable but 
a type-switch with a default unacceptable?

> I've got a very efficient system set up right now with great error handling. 
> I don't see why the same capability can't exist in the language, especially 
> when you can choose to completely ignore it. Hopefully more people would use 
> it and we'd stop seeing so many "unknown error" dialogs.


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

Reply via email to