Definition
1
2
3
4
5
6
7
8
9
10
| /// A value that represents either a success or a failure, including an
/// associated value in each case.
@frozen public enum Result<Success, Failure> where Failure : Error {
/// A success, storing a `Success` value.
case success(Success)
/// A failure, storing a `Failure` value.
case failure(Failure)
}
|
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| struct Person: Decodable {
let name: String
let age: Int
}
extension String: Error {}
func loadPerson(from json: String) -> Result<Person, Error> {
guard let data = json.data(using: .utf8) else {
return .failure("Error in encoding string using utf8.")
}
do {
let person = try JSONDecoder().decode(Person.self, from: data)
return .success(person)
} catch {
return .failure(error)
}
}
let json = """
{
"name": "Jack Reacher",
"age": 35
}
"""
let result = loadPerson(from: json)
switch result {
case .success(let person):
print(person.name) // Jack Reacher
case .failure(let error):
print(error.localizedDescription)
}
|
Its functions for transformaing associated sucess and failure values:
1
2
3
4
5
6
7
| @inlinable public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> Result<NewSuccess, Failure>
@inlinable public func mapError<NewFailure>(_ transform: (Failure) -> NewFailure) -> Result<Success, NewFailure> where NewFailure : Error
@inlinable public func flatMap<NewSuccess>(_ transform: (Success) -> Result<NewSuccess, Failure>) -> Result<NewSuccess, Failure>
@inlinable public func flatMapError<NewFailure>(_ transform: (Failure) -> Result<Success, NewFailure>) -> Result<Success, NewFailure> where NewFailure : Error
|
Conversion between Result
and throwing expression
Result
➡️ throwing expression
The get()
function of Result
enables us to convert a Result
value to a throwing expression.
1
| @inlinable public func get() throws -> Success
|
1
| let optionalPerson = try? loadPerson(from: json).get()
|
Throwing expression ➡️ Result
Below is a throwing version of function loadPerson(from:)
:
1
2
3
4
5
6
7
| func throwingLoadPerson(from json: String) throws -> Person {
guard let data = json.data(using: .utf8) else {
throw "Error in encoding string using utf8."
}
let person = try JSONDecoder().decode(Person.self, from: data)
return person
}
|
Wrap the throwing call as Result
:
1
| let personResult = Result { try throwingLoadPerson(from: json) }
|
The conversion is made possible by this function:
1
2
3
4
5
6
7
8
| extension Result where Failure == Error {
/// Creates a new result by evaluating a throwing closure, capturing the
/// returned value as a success, or any thrown error as a failure.
///
/// - Parameter body: A throwing closure to evaluate.
public init(catching body: () throws -> Success)
}
|
Use with Never
Since Never
conforms to Error
protocol, it can be used as the failure value type in Result
.
1
2
3
4
5
6
7
8
| let result: Result<Int, Never> = .success(100)
switch result {
case .success(let number):
print(number)
//case .failure(_): // compiler won't yell at you without the failure case.
// break
}
|