Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ResultProtocol.fanout(_:) as an alternative to &&& operator #204

Merged
merged 2 commits into from
Dec 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Result/ResultProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public extension ResultProtocol {
ifFailure: Result<U, Error>.failure)
}

/// Returns a Result with a tuple of the receiver and `other` values if both
/// are `Success`es, or re-wrapping the error of the earlier `Failure`.
public func fanout<R: ResultProtocol>(_ other: @autoclosure () -> R) -> Result<(Value, R.Value), Error>
where Error == R.Error
{
return self.flatMap { left in other().map { right in (left, right) } }
}

/// Returns a new Result by mapping `Failure`'s values using `transform`, or re-wrapping `Success`es’ values.
public func mapError<Error2>(_ transform: (Error) -> Error2) -> Result<Value, Error2> {
return flatMapError { .failure(transform($0)) }
Expand Down Expand Up @@ -119,7 +127,7 @@ infix operator &&& : LogicalConjunctionPrecedence
public func &&& <L: ResultProtocol, R: ResultProtocol> (left: L, right: @autoclosure () -> R) -> Result<(L.Value, R.Value), L.Error>
where L.Error == R.Error
{
return left.flatMap { left in right().map { right in (left, right) } }
return left.fanout(right)
}

precedencegroup ChainingPrecedence {
Expand Down
40 changes: 19 additions & 21 deletions Tests/ResultTests/ResultTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ final class ResultTests: XCTestCase {
XCTAssert(Result(nil, failWith: error) == failure)
}

func testFanout() {
let resultSuccess = success.fanout(success)
if let (x, y) = resultSuccess.value {
XCTAssertTrue(x == "success" && y == "success")
} else {
XCTFail()
}

let resultFailureBoth = failure.fanout(failure2)
XCTAssert(resultFailureBoth.error == error)

let resultFailureLeft = failure.fanout(success)
XCTAssert(resultFailureLeft.error == error)

let resultFailureRight = success.fanout(failure2)
XCTAssert(resultFailureRight.error == error2)
}

func testBimapTransformsSuccesses() {
XCTAssertEqual(success.bimap(
success: { $0.characters.count },
Expand Down Expand Up @@ -168,26 +186,6 @@ final class ResultTests: XCTestCase {
let result = Result<String, AnyError>.success("fail").tryMap(tryIsSuccess)
XCTAssert(result == failure)
}

// MARK: Operators

func testConjunctionOperator() {
let resultSuccess = success &&& success
if let (x, y) = resultSuccess.value {
XCTAssertTrue(x == "success" && y == "success")
} else {
XCTFail()
}

let resultFailureBoth = failure &&& failure2
XCTAssert(resultFailureBoth.error == error)

let resultFailureLeft = failure &&& success
XCTAssert(resultFailureLeft.error == error)

let resultFailureRight = success &&& failure2
XCTAssert(resultFailureRight.error == error2)
}
}

final class NoErrorTests: XCTestCase {
Expand Down Expand Up @@ -269,6 +267,7 @@ extension ResultTests {
("testMapRewrapsFailures", testMapRewrapsFailures),
("testInitOptionalSuccess", testInitOptionalSuccess),
("testInitOptionalFailure", testInitOptionalFailure),
("testFanout", testFanout),
("testBimapTransformsSuccesses", testBimapTransformsSuccesses),
("testBimapTransformsFailures", testBimapTransformsFailures),
("testErrorsIncludeTheSourceFile", testErrorsIncludeTheSourceFile),
Expand All @@ -291,7 +290,6 @@ extension ResultTests {
// ("testTryProducesSuccessesForOptionalAPI", testTryProducesSuccessesForOptionalAPI),
("testTryMapProducesSuccess", testTryMapProducesSuccess),
("testTryMapProducesFailure", testTryMapProducesFailure),
("testConjunctionOperator", testConjunctionOperator),
]
}
}
Expand Down