Skip to content

Commit

Permalink
Merge pull request #118 from bwhiteley/tryMap
Browse files Browse the repository at this point in the history
Add a version of `map` that converts thrown errors to `Failure`s.
  • Loading branch information
NachoSoto committed Dec 9, 2015
2 parents 7a54468 + 2e5749a commit 9f2c108
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Result/Result.swift
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,14 @@ public func >>- <T, U, Error> (result: Result<T, Error>, @noescape transform: T
}


// MARK: - ErrorTypeConvertible conformance

/// Make NSError conform to ErrorTypeConvertible
extension NSError: ErrorTypeConvertible {
public static func errorFromErrorType(error: ErrorType) -> NSError {
return error as NSError
}
}


import Foundation
23 changes: 23 additions & 0 deletions Result/ResultType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,29 @@ public extension ResultType {
}
}

/// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s.
public protocol ErrorTypeConvertible: ErrorType {
typealias ConvertibleType = Self
static func errorFromErrorType(error: ErrorType) -> ConvertibleType
}

public extension ResultType where Error: ErrorTypeConvertible {

/// Returns the result of applying `transform` to `Success`es’ values, or wrapping thrown errors.
public func tryMap<U>(@noescape transform: Value throws -> U) -> Result<U, Error> {
return flatMap { value in
do {
return .Success(try transform(value))
}
catch {
let convertedError = Error.errorFromErrorType(error) as! Error
// Revisit this in a future version of Swift. https://twitter.com/jckarter/status/672931114944696321
return .Failure(convertedError)
}
}
}
}

// MARK: - Operators

infix operator &&& {
Expand Down
12 changes: 11 additions & 1 deletion ResultTests/ResultTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ final class ResultTests: XCTestCase {
XCTAssertNil(result.error)
}

func testTryMapProducesSuccess() {
let result = success.tryMap(tryIsSuccess)
XCTAssert(result == success)
}

func testTryMapProducesFailure() {
let result = Result<String, NSError>.Success("fail").tryMap(tryIsSuccess)
XCTAssert(result == failure)
}

// MARK: Operators

func testConjunctionOperator() {
Expand Down Expand Up @@ -146,7 +156,7 @@ func attempt<T>(value: T, succeed: Bool, error: NSErrorPointer) -> T? {
}

func tryIsSuccess(text: String?) throws -> String {
guard let text = text else {
guard let text = text where text == "success" else {
throw error
}

Expand Down

0 comments on commit 9f2c108

Please sign in to comment.