My 2 cents:
Generic errors have caused me problems on multiple occasions.They often make it
difficult to handle and pass-through arbitrary errors. This pseudo Swift3 code
is what I have resorted to doing on some projects.
```
enum MyError : Error
{
…
case wrappedError( Error )
}
```
I would go so far as to say that generic errors are an anti-pattern in Swift.
- Chris
> On Aug 14, 2016, at 6:04 PM, Jon Shier via swift-evolution
> <[email protected]> wrote:
>
> Yes, if you return a single error type it works fine. However, since
> Alamofire wraps the underlying networking frameworks there’s a need to return
> the errors returned from them as well, which are now returned as Error. In
> order to let these errors be returned alongside Alamofire’s errors we’d
> either have to get rid of the generic error and just use Error or wrap all
> errors in our error type. So far the least painful method seems to be just
> getting rid of the generic error and returning Error for everything. That way
> users will use the same logic they would have had to use anyway and can also
> provide their own error wrapper if they want. Thankfully (or unfortunately,
> depending on your point of view), the new pattern is to cast out the various
> error types, so the previous concern about having to do that is no longer an
> issue.
>
>
> Jon
>
>> On Aug 14, 2016, at 4:18 AM, Charles Srstka <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>> On Aug 14, 2016, at 2:34 AM, Jon Shier <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>> Sorry Charles, I should’ve been more specific. This isn’t about some
>>> other type named Error being usable, but about our doubly generic Result
>>> and other types being usable with Error as the generic error type. If we
>>> have Result defined as:
>>>
>>> public enum Result<Value, ErrorType: Error> {
>>> case success(Value)
>>> case failure(ErrorType)
>>> }
>>>
>>> then attempting to create the type Result<Whatever, Error> results in the
>>> error message I posted. For methods that previously returned
>>> Result<Whatever, NSError>, where the NSError is either a system error or an
>>> Alamofire one, this is something of a problem. Of course, removing the
>>> generic error type fixes this but may have an undesirable usability impact,
>>> as making Result double generic was the primary reason behind the quick
>>> upgrade between Alamofire 2 and 3. I think it’s less of a problem now, as
>>> having to enumerate all of the different expected error types is how user’s
>>> are supposed to interact with Error in the first place, but at the time it
>>> wasn’t desirable to try and force everything through ErrorProtocol for that
>>> reason. Perhaps this is a good compromise, where instead of returning all
>>> NSErrors from the framework and allowing consumers to add their own to the
>>> mix we’ll just create our own AFError type (whether enum or struct) and
>>> then anything coming back will have to be checked for that type in addition
>>> to the system types. From my testing it looks like users could still wrap
>>> everything coming in by capturing the underlying Error.
>>
>> Still seems to be working well, unless I’m misunderstanding what you’re
>> trying to do:
>>
>> import Foundation
>>
>> enum Result<Value, ErrorType: Error> {
>> case success(Value)
>> case failure(ErrorType)
>> }
>>
>> struct MyThing {
>> enum Error: Swift.Error, LocalizedError {
>> case doesNotCompute
>> case imSorryDave
>> case mustSterilize
>> case irrelevant
>> case endOfLine
>>
>> var failureReason: String? {
>> switch self {
>> case .doesNotCompute:
>> return "Does Not Compute! Does Not Compute! Does Not
>> Compute!"
>> case .imSorryDave:
>> return "I'm sorry Dave, I'm afraid I can't do that."
>> case .mustSterilize:
>> return "Error! Must Sterilize! Must
>> Steeerrrrilllliiiiiiizzzzzzeeeeeee"
>> case .irrelevant:
>> return "Irrelevant. Resistance is futile."
>> case .endOfLine:
>> return "End of Line!"
>> }
>> }
>> }
>>
>> func trySomething(shouldWork: Bool, completionHandler: (Result<String,
>> Error>) -> ()) {
>> if shouldWork {
>> completionHandler(.success("It worked!"))
>> } else {
>> completionHandler(.failure(Error.imSorryDave))
>> }
>> }
>> }
>>
>> let thing = MyThing()
>>
>> let completionHandler = { (result: Result<String, MyThing.Error>) in
>> switch result {
>> case let .success(value):
>> print("returned '\(value)'")
>> case let .failure(error):
>> print("error: \(error.localizedDescription)")
>> }
>> }
>>
>> thing.trySomething(shouldWork: true, completionHandler: completionHandler)
>> thing.trySomething(shouldWork: false, completionHandler: completionHandler)
>>
>> returned 'It worked!'
>> error: The operation couldn’t be completed. I'm sorry Dave, I'm afraid I
>> can't do that.
>> Program ended with exit code: 0
>>
>> Charles
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution