<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 27, 2017, at 11:04 PM, David Waite <<a href="mailto:david@alkaline-solutions.com" class="">david@alkaline-solutions.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 27, 2017, at 2:08 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><br class="Apple-interchange-newline">On Feb 27, 2017, at 1:46 PM, David Waite via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div></blockquote><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">Add more layers, and it can be very mysterious why a call failed. Java at least captures stack traces in this case to aid in technical support in diagnosing the error.</div><div class=""><br class=""></div><div class="">Wrapping exceptions also prevents an aggregate of errors from different subsystems being handled as a category, such as having a catch block handle RecoverableError generically</div></div></div></blockquote><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">An interesting solution that has emerged in Ruby to keep library authors from wrapping exceptions is by decorating the existing exception. Exceptions are caught via pattern matching (same as in Swift), so rather than wrap an extension, they extend the error instance with a library-specific module (e.g. swift protocol). So while the error may be a IOError in ruby, you can still catch it via ‘rescue JSONError’</div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">If I understand this correctly it sounds like introducing a library would create protocols to categorize errors and add retroactive conformances to these protocols for errors thrown by its dependencies? That is an interesting approach. But it requires knowing the concrete types of the possible errors all the way down the stack (you can’t add a conformance to an existential). This seems very problematic to me, especially in a language where creating new error types is as easy as it is in Swift.</div></div></blockquote><div class=""><br class=""></div>I believe it is something that even Objective C can’t do; extend a single instance of a type to support a protocol.</div></div></div></blockquote><div><br class=""></div><div>Ok, I missed that it was a single instance, not all values with a given error type.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">You can still do really interesting things with categories of errors, such as extend existing types to support a protocol, and putting categorization logic on third party errors yourself.</div><div class=""><br class=""></div><div class="">That breaks though if every library does</div><div class=""><br class=""></div><div class="">struct MyError: Error {</div><div class=""> let innerError: Error</div><div class="">}</div><div class=""><br class=""></div><div class="">in order to have a typed throw. </div></div></div></blockquote><div><br class=""></div><div>Did you see my suggestion for adding underlying and originating error properties to the `Error` protocol? That would solve the problem of every library doing this themselves and make it much easier to identify what happened at the bottom of the stack when you really need to know that (without manually extracting wrapped errors all the way down).</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">Error handling is messy, there’s no doubt about that. I would like to have as many tools at my disposal as possible. Error types is one of those tools.</div></blockquote><div class=""><div class=""><br class=""></div></div><div class="">I’m still trying to mentally put together the elevator pitch for typed throws. How do I explain to new/junior developers and developers coming from other languages when to do typed throws, and when not to?</div></div></div></div></blockquote><div><br class=""></div><div>IMO this is not that much different than any other aspect of API design. This isn’t so much an elevator pitch as an education that error handling is messy and complicated and requires just as much thought in designing an API as the happy path does. Nobody enjoys thinking about errors. This is an opportunity to help teach junior developers to think more carefully about them.</div><div><br class=""></div><div>Help junior developers learn to think about users of an API and think about dependencies and coupling. When a user is calling this API how might they want to handle errors that might be thrown? How can the error type help facilitate that? On the other hand, when is an API exposing too much concrete type information to callers that creates unnecessary coupling? When that is the case, how can we best remove enough type information to avoid that coupling (i.e. wrapping, exposing an existential, etc)? </div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div></div><div class="">-DW</div><div class=""><br class=""></div></div></div></blockquote></div><br class=""></body></html>