Swiftpack.co - Package - antitypical/Result

Result

Build Status Carthage compatible CocoaPods Reference Status

This is a Swift µframework providing Result<Value, Error>.

Result<Value, Error> values are either successful (wrapping Value) or failed (wrapping Error). This is similar to Swift’s native Optional type: success is like some, and failure is like none except with an associated Error value. The addition of an associated Error allows errors to be passed along for logging or displaying to the user.

Using this µframework instead of rolling your own Result type allows you to easily interface with other frameworks that also use Result.

Use

Use Result whenever an operation has the possibility of failure. Consider the following example of a function that tries to extract a String for a given key from a JSON Dictionary.

typealias JSONObject = [String: Any]

enum JSONError: Error {
    case noSuchKey(String)
    case typeMismatch
}

func stringForKey(json: JSONObject, key: String) -> Result<String, JSONError> {
    guard let value = json[key] else {
        return .failure(.noSuchKey(key))
    }
    
    guard let value = value as? String else {
        return .failure(.typeMismatch)
    }

    return .success(value)
}

This function provides a more robust wrapper around the default subscripting provided by Dictionary. Rather than return Any?, it returns a Result that either contains the String value for the given key, or an ErrorType detailing what went wrong.

One simple way to handle a Result is to deconstruct it using a switch statement.

switch stringForKey(json, key: "email") {

case let .success(email):
    print("The email is \(email)")
    
case let .failure(.noSuchKey(key)):
    print("\(key) is not a valid key")
    
case .failure(.typeMismatch):
    print("Didn't have the right type")
}

Using a switch statement allows powerful pattern matching, and ensures all possible results are covered. Swift 2.0 offers new ways to deconstruct enums like the if-case statement, but be wary as such methods do not ensure errors are handled.

Other methods available for processing Result are detailed in the API documentation.

Result vs. Throws

Swift 2.0 introduces error handling via throwing and catching Error. Result accomplishes the same goal by encapsulating the result instead of hijacking control flow. The Result abstraction enables powerful functionality such as map and flatMap, making Result more composable than throw.

Since dealing with APIs that throw is common, you can convert such functions into a Result by using the materialize method. Conversely, a Result can be used to throw an error by calling dematerialize.

Higher Order Functions

map and flatMap operate the same as Optional.map and Optional.flatMap except they apply to Result.

map transforms a Result into a Result of a new type. It does this by taking a function that transforms the Value type into a new value. This transformation is only applied in the case of a success. In the case of a failure, the associated error is re-wrapped in the new Result.

// transforms a Result<Int, JSONError> to a Result<String, JSONError>
let idResult = intForKey(json, key:"id").map { id in String(id) }

Here, the final result is either the id as a String, or carries over the failure from the previous result.

flatMap is similar to map in that it transforms the Result into another Result. However, the function passed into flatMap must return a Result.

An in depth discussion of map and flatMap is beyond the scope of this documentation. If you would like a deeper understanding, read about functors and monads. This article is a good place to start.

Integration

Carthage

  1. Add this repository as a submodule and/or add it to your Cartfile if you’re using carthage to manage your dependencies.
  2. Drag Result.xcodeproj into your project or workspace.
  3. Link your target against Result.framework.
  4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Result.)

Cocoapods

pod 'Result', '~> 5.0'

Swift Package Manager

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "MyProject",
    targets: [],
    dependencies: [
        .package(url: "https://github.com/antitypical/Result.git",
                 from: "5.0.0")
    ]
)

Github

link
Stars: 2469

Dependencies

Releases

5.0.0 - 2019-05-27 13:15:16

  • Adopt Swift 5's built-in Result type when compiler(>=5.0) (#280)
  • Deprecate NoError in favor of Never, which now conforms to Error (#286)

4.1.0 - 2019-01-01 13:18:45

NEW

  • Add compatibility with Swift 5's Result (#278)
    • Add Result.Success typealias
    • Add Result.Failure typealias
    • Add init(catching body: () throws -> Success) and deprecate init(attempt f: () throws -> Value)
    • Add func get() throws -> Success and deprecate func dematerialize() throws -> Value

See https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md and https://forums.swift.org/t/accepted-with-modifications-se-0235-add-result-to-the-standard-library/18603 for further information of the Swift 5's Result.

4.0.1 - 2018-12-31 08:51:55

NEW

  • Add explicit support for Xcode 10 / Swift 4.2.

4.0.0 - 2018-04-27 04:35:48

CHANGED

  • Result now requires Swift 4.0/Xcode 9 at least. Swift 4.1/Xcode 9.3 are supported as well (#217, #237, #241, #245, #252, #256, #258, #259, #264)
  • Remove deprecated and unavailable APIs from Result 2.x (Swift 2.x) (#220, #226)
  • Rename ErrorProtocolConvertible to ErrorConvertible (#232)
  • Reduce the responsibility of ResultProtocol (#235, #243)
  • Deprecate materialize functions (#239)
  • Make try functions unavailable (#253)

NEW

  • Add LocalizedError conformance to AnyError on Linux (#227)
  • Add AnyError overloads for init(_:) and init(attempt:) (#236)

3.2.4 - 2017-09-27 04:21:26

  • [CHANGED]: Deprecate try functions in favor of Result.init(attempt:) (#251)

3.2.3 - 2017-05-29 04:50:05

  • [CHANGED]: Deprecate ErrorProtocolConvertible in favor of ErrorConvertible (#230)

3.2.2 - 2017-05-16 16:50:01

  • [FIXED]: Improve AnyError support in Result.init(attempt:) (#224)

3.2.1 - 2017-03-04 12:36:08

  • [FIXED]: Swift 3.1 compatibility issue on Linux (#212, #214)

3.2.0 - 2017-03-01 04:55:06

  • [NEW]: Add ResultProtocol.bimap(success:failure:) method (#116, #205)
  • [NEW]: Add ResultProtocol.fanout(_:) as an alternative to &&& operator (#204)
  • [NEW]: Add LocalizedError conformance to AnyError on Darwin platforms (#210)
  • [CHANGED]: Deprecate >>- and &&& operators (#206)

3.1.0 - 2016-11-29 04:37:44

  • [NEW]: Add Equatable conformance to NoError (#200, #201)
  • [NEW]: Add type-erased AnyError for generic contexts. materialize overload for AnyError is also added (#198)
  • [CHANGED]: materialize for NSError is now deprecated in favor of the overload for AnyError (#198)

3.0.0 - 2016-09-11 17:24:15

  • [CHANGED]: Drop Swift 2.x support
  • [CHANGED]: Swift 3 API Design Guidelines
  • [CHANGED]: Support for Swift 3.0

API changes from 2.x:

  • Result
    • .Success to .success
    • .Failure to .failure
  • ResultType to ResultProtocol
    • recoverWith(_:) to recover(with:)
  • ResultErrorType to Swift.Error
  • ErrorTypeConvertible to ErrorProtocolConvertible
    • errorFromErrorType_:) to error(from:)

3.0.0-alpha.4 - 2016-08-24 11:51:10

  • [CHANGED]: Drop Swift 2.x support
  • [CHANGED]: Swift 3 API Design Guidelines
  • [CHANGED]: Support for Swift 3.0 Preview 6

API changes from 2.x:

  • Result
    • .Success to .success
    • .Failure to .failure
  • ResultType to ResultProtocol
    • recoverWith(_:) to recover(with:)
  • ResultErrorType to Swift.Error
  • ErrorTypeConvertible to ErrorProtocolConvertible
    • errorFromErrorType_:) to error(from:)

3.0.0-alpha.3 - 2016-08-17 00:54:17

  • [CHANGED]: Drop Swift 2.x support
  • [CHANGED]: Swift 3 API Design Guidelines
  • [CHANGED]: Support for Swift 3.0 Preview 4

API changes from 2.x:

  • Result
    • .Success to .success
    • .Failure to .failure
  • ResultType to ResultProtocol
    • recoverWith(_:) to recover(with:)
  • ResultErrorType to Swift.Error
  • ErrorTypeConvertible to ErrorProtocolConvertible
    • errorFromErrorType_:) to error(from:)

3.0.0-alpha.2 - 2016-08-07 00:32:38

  • [CHANGED]: Drop Swift 2.x support
  • [CHANGED]: Swift 3 API Design Guidelines
  • [CHANGED]: Support for Swift 3.0 Preview 4

API changes from 2.x:

  • Result
    • .Success to .success
    • .Failure to .failure
  • ResultType to ResultProtocol
    • recoverWith(_:) to recover(with:)
  • ResultErrorType to Swift.Error
  • ErrorTypeConvertible to ErrorProtocolConvertible
    • errorFromErrorType_:) to error(from:)

- 2016-07-15 05:01:58

  • [FIXED]: Xcode project settings to suppress warning on Xcode 8 (#174).

3.0.0-alpha.1 - 2016-07-14 00:43:42

  • [CHANGED]: Drop Swift 2.x support
  • [CHANGED]: Swift 3 API Design Guidelines
  • [CHANGED]: Support for Swift 3.0 Preview 1 and 2

API changes from 2.x:

  • Result
    • .Success to .success
    • .Failure to .failure
  • ResultType to ResultProtocol
    • recoverWith(_:) to recover(with:)
  • ResultErrorType to ErrorProtocol
  • ErrorTypeConvertible to ErrorProtocolConvertible
    • errorFromErrorType_:) to error(from:)

2.1.2 - 2016-07-01 04:54:12

  • [FIXED]: Device builds on Xcode 8 (#169).

2.1.1: Results, Not Excuses - 2016-06-18 23:46:51

  • [NEW]: Support for Swift 2.3 and Xcode 8 (Swift 2.2 is still supported)
  • [NEW]: Whole module optimization has been turned on

2.1.0: Future Results - 2016-06-10 01:37:15

  • [CHANGED]: recover, recoverWith, ==, !=, ??, and >>- are now defined in terms of ResultType
  • [CHANGED]: ConvertibleType was removed from ErrorTypeConvertible
  • [CHANGED]: Swift 3 support has been updated to the 2016-05-31 snapshot
  • [NEW]: Unused results will now trigger a warning

2.0.0: A Portable Result - 2016-03-27 01:09:22

[CHANGED]: Swift 2.2 or later is required. [NEW]: Swift 3.0 support. [NEW]: Linux support. (Some limitations exist.)

1.0.2: A Swift Result - 2016-01-29 21:28:06

  • [IMPROVED]: More in-depth README (#62).
  • [NEW]: Support for Swift Package Manager (#126).
  • [NEW]: Added a NoError ErrorType (#132).

1.0.1: A New Beginning - 2015-12-09 23:09:21

  • [NEW]: Added Result.tryMap accepting a throwing function (#118).
  • [NEW]: Added Result(attempt:): a non-@autoclosure version of the constructor (#125).
  • [CHANGED]: Setting explicit deployment target to tvOS 9.0 and watchOS 2.0 in Xcode 7.2 (#127).

1.0: Real Results - 2015-11-26 00:14:09

:tada: 1.0! :tada:

This has been in beta for a while. Thanks to everyone who helped improve it and push it forward during that time.

Summary of changes since the 0.4 series of releases (See the 0.5 and 0.6 series of beta releases for more detailed info):

  • [NEW]: Swift 2.0 support
  • [NEW]: Translate to and from Swift 2 functions using throw
  • [NEW]: tvOS support
  • [CHANGED]: Removed dependency on Box

0.6.0 Beta 6: Apple TV, take three - 2015-10-31 15:55:55

  • [fixed] Added Apple TV deployment target to the podspec
  • [fixed] Added second materialize without @autoclosure to be compatible with trailing closure syntax

0.6 Beta 5: remember that TV thing? - 2015-10-23 21:11:44

  • [new] Apple TV scheme is available again (note: it requires Xcode 7.1)

0.4.5: Frozen Box - 2015-10-13 08:20:19

  • [fixed] Add a version constraint to Box dependency for compatibility with Swift 1.2.

0.6 Beta 4: Bitcode Build - 2015-10-08 07:33:24

Updated the build settings so that Result can be built with Carthage for targets that require bitcode.

0.6 Beta 3: Just kidding about that TV thing - 2015-09-16 23:20:44

Removed the tvOS scheme from the project in order to fix builds with Carthage and Xcode 7. We'll re-add this with Xcode 7.1.

0.6 Beta 2: Materialize Build - 2015-09-15 21:38:00

  • [new] free materialize function that takes a function of the type () throws -> T and returns Result<T, NSError>
  • [new] tvOS Support
  • [Fixed] Explicitly set code signing to work around bugs in xcodebuild

0.5: Swift 2 Beta - 2015-06-09 18:11:05

  • [improved] Removes Box dependency because Swift 2 supports multi-payload enums.