Search code examples
swiftfoundation

How does "data.map(Result.success)" work and Return a type of Result<Data, Error>?


I stumbled upon the following piece of code in this tutorial and I cannot figure out how the return value of data.map(Result.success) works.

So far, I knew .map to work with $0 in the closure. In this case, only Result.success is provided. How is the return value of this call of type Result<Data, Error>?

class DataLoader {
    func request(_ endpoint: Endpoint,
             then handler: @escaping (Result<Data, NError>) -> Void) {
        guard let url = endpoint.url else {
            return handler(.failure(NError.invalidURL))
        }

        let urlSession = URLSession(configuration: .default)
        let task = urlSession.dataTask(with: url) {
            data, _, error in

            let result = data.map(Result.success) ??
                .failure(NError.network)

            handler(result)
        }

        task.resume()
    }
}

Solution

  • The map you are seeing here is not the map that is usually called on arrays/sequences that transforms each element into something else. It is Optional.map.

    map in this case does this:

    • if the optional has a value, transforms the value wrapped inside the optional using the closure, and returns the transformed value wrapped in an optional.
    • if the optional is nil, returns nil.

    In your code, let result = data.map(Result.success) ?? .failure(NError.network) can thus be rewritten like this:

    let result: Result<Data, Error>
    if data == nil {
        result = .failure(NError.network)
    } else {
        result = Result.success(data!)
    }
    

    As you can see Result.success is passed as a function here. If you are used to seeing the $0 syntax, here's how it will look if it were written with $0:

    data.map { Result.success($0) }