On Thu, Nov 2, 2017 at 12:21 PM Jon Shier <j...@jonshier.com> wrote: > The Result type I’ve outlined includes the functions necessary to > translate between do try catch and Result. But I fundamentally disagree > with your characterization of Swift’s error handling. At most, Swift > strives to hide the line between normal functions and error throwing ones, > but only until the developer needs access to those errors. If you’re using > an API that takes throwing functions and handles the do / catch for you, > then sure, you’ll never see the result of those functions as anything more > than the values you get from those APIs But anyone writing their own try / > catch statements is quite clearly going to see the result/error separation > that Result encapsulates. In quite a few cases, passing an encapsulation > around rather than having to either mark all functions as throwing in order > to propagate an error, or constantly implementing try / catch, results is > code that is far easier to read, write, and reason about it. >
I would think the opposite is true. let value = compute() Looking at this line of code, I have no idea whether I should expect to handle errors or not. Does "compute" return a Result<> or just the value I want? If we used throwing instead, it's obvious without any other context that an error can occur there: let value = try compute() That's another explicit design choice in Swift, that "try" marks expressions so it's very clear which expressions can throw, rather than just being a block that surrounds an arbitrarily long amount of code. Result<> provides none of that context. > Of course it’s not an absolute solution, which is why the ability to turn > a Result into a throwing function exists, but instead a complement to the > current error handling in Swift. > > > Jon > > > On Nov 2, 2017, at 3:11 PM, Tony Allevato <tony.allev...@gmail.com> wrote: > > > > On Thu, Nov 2, 2017 at 11:58 AM Jon Shier <j...@jonshier.com> wrote: > >> You would continue to be free to discourage the usage of Result for >> whatever you want. For the rest of us, Result isn’t intended to replace >> throws or do/catch, but provide a way to accomplish things in a much more >> compact and sometimes natural way. As with any API it could be used >> stupidly. But frankly, what developers what to do to wrap their errors is >> up to them. >> > > And it still is, with the Result implementations that are available to > third-parties today. > > My concerns regarding Result aren't about my personal discouragement of > its use, but the *reasons* why I discourage its use. The Swift language > very deliberately draws a line between result outcomes that are return > values and error outcomes that are thrown, and it implements not only > standard library types but also language syntactic sugar to support those. > > If someone wants to depend on a third-party Result<> to conflate > successful outcomes and error outcomes in their own code, that's absolutely > their right. But entry into the standard library has a much higher bar, and > what we're talking about here is adding a feature that now would give users > two disparate and incompatible ways (without explicit transformations, or > other syntactic sugar) of handling errors. That makes me uneasy from the > point of view of both an API designer and consumer, and just restating that > it's a common pattern and people want it doesn't address those concerns. > > > > >> Adding Result is just a way of blessing a result/error representation, >> since it has become a rather common pattern. If you’ve looked at the >> implementation I showed, you’ll see that there’s far more functionality >> than just a Result type, including API for converting back and forth from >> throwing functions, as well as functional transforms. Result is a >> complement to try do catch, not a replacement. >> >> >> >> Jon >> >> >> >> >> On Nov 2, 2017, at 2:48 PM, Tony Allevato <tony.allev...@gmail.com> >> wrote: >> >> >> >> On Thu, Nov 2, 2017 at 11:32 AM Jon Shier <j...@jonshier.com> wrote: >> >>> That’s been an argument against Result for 2 years now. The usefulness >>> of the type, even outside of whatever asynchronous language support the >>> core team comes up with, perhaps this year, perhaps next year, is still >>> very high. Even as something that just wraps throwing functions, or >>> otherwise exists as a local, synchronous value, it’s still very useful as >>> way to encapsulate the value/error pattern. >>> >> >> This is one of the parts that concerns me, actually. The beauty of >> Swift's error design is that function results denote expected/successful >> outcomes and thrown errors denote unexpected/erroneous outcomes. Since they >> are different, each is handled through its own language constructs, and >> since the language itself supports it (rather than being entirely >> type-based), you don't have the proliferation of unwrapping boilerplate >> that you have with Result<>. >> >> In our own code bases, I actively discourage the use of Result<> in that >> way, because it tries to cram both of those concepts into the >> expected/successful outcomes slot in the language. For asynchronous APIs >> that's somewhat unavoidable today, but if that's going to change, I'd >> rather the language focus on a way that's consistent with other error >> handling already present in Swift. >> >> Adding an API to the standard library is the core team saying "this is >> blessed as something around which we support APIs being designed." IMO, I'd >> prefer it if the language did *not* bless two disparate ways of >> communicating error outcomes but rather converged on one. >> >> IMO, "things aren't happening fast enough" isn't great motivation for >> putting something permanently into the standard library or the language >> without considering the context of other things going on around it. If >> you're going to propose something that overlaps with asynchronous APIs, it >> only helps your case if you can discuss how it can integrate—rather than >> collide—with those efforts. >> >> >> >> >>> That pattern will likely never go away. Additionally, having the Result >>> type in the standard library removes a source of conflict between all other >>> Result implementations, which are becoming more common. >>> >>> >>> On Nov 2, 2017, at 2:26 PM, Tony Allevato <tony.allev...@gmail.com> >>> wrote: >>> >>> Given that the Swift team is currently working on laying the groundwork >>> for asynchronous APIs using an async/await model, which would presumably >>> tie the throwing cases more naturally into the language than what is >>> possible using completion-closures today, are we sure that this wouldn't >>> duplicate any efforts there or be made obsolete through other means? >>> >>> In other words, while Result<> can be a very useful foundational >>> component on its own, I think any proposal for it can't be made in >>> isolation, but very much needs to consider other asynchronous work going on >>> in the language. >>> >>> >>> On Thu, Nov 2, 2017 at 11:15 AM Jon Shier via swift-evolution < >>> swift-evolution@swift.org> wrote: >>> >>>> You don’t lose it, it’s just behind `Error`. You can cast out whatever >>>> strong error type you need without having to bind an entire type to it >>>> generically. If getting a common error type out happens a lot, I usually >>>> add a convenience property to `Error` to do the cast for me. Plus, having >>>> to expose an entire new error wrapper is just a non starter for me and >>>> doesn’t seem necessary, given how Result is currently used in the >>>> community. >>>> >>>> >>>> Jon >>>> >>>> >>>> On Nov 2, 2017, at 2:12 PM, Dave DeLong <sw...@davedelong.com> wrote: >>>> >>>> I think I’d personally rather see this done with a generic error as >>>> well, like: >>>> >>>> enum GenericResult<T, E: Error> { >>>> case success(T) >>>> case failure(E) >>>> } >>>> >>>> And a typealias: >>>> >>>> typealias Result<T> = GenericResult<T, AnyError> >>>> >>>> This would require an “AnyError” type to type-erase a specific Error, >>>> but I’ve come across many situations where a strongly-typed error is >>>> *incredibly >>>> *useful, and I’d be reluctant to see that thrown away. >>>> >>>> Dave >>>> >>>> On Nov 2, 2017, at 12:08 PM, Jon Shier via swift-evolution < >>>> swift-evolution@swift.org> wrote: >>>> >>>> Swift-Evolution: >>>> I’ve written a first draft of a proposal to add Result<T> to the >>>> standard library by directly porting the Result<T> type used in Alamofire >>>> to the standard library. I’d be happy to implement it (type and tests for >>>> free!) if someone could point me to the right place to do so. I’m not >>>> including it directly in this email, since it includes the full >>>> implementation and is therefore quite long. (Discourse, please!) >>>> >>>> >>>> https://github.com/jshier/swift-evolution/blob/master/proposals/0187-add-result-to-the-standard-library.md >>>> >>>> >>>> Thanks, >>>> >>>> Jon Shier >>>> >>>> >>>> _______________________________________________ >>>> 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 >>>> >>> >>> >> >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution