pacification
pacification

Reputation: 6018

"Missing return in a closure expected to return 'SomeType'" error in .map

I have the fallowing code:

struct AInt {
    var aInt: Int
}

struct ADouble {
    var aDouble: Double

    static func convert(aInt: AInt) throws -> ADouble {
        return ADouble(aDouble: Double(aInt.aInt))
    }
}

struct B {
    func doAction(aInts: [AInt]) throws -> [ADouble] {
        return aInts.map { aInt in
            do {
                try ADouble.convert(aInt)
            }
            catch {
                print(error)
            }
        }
    // ^^^ error here: Missing return in a closure expected to return 'ADouble'
    }
}

let aInts = [AInt(aInt: 2), AInt(aInt: 3)]
let b = B()
do {
    print(try b.doAction(aInts))
}
catch {}

When i'm trying to convert [AInt] to [ADouble] in .map using function that can throw error, i get this error:
Missing return in a closure expected to return 'ADouble'.
Well, i decided to add return statement in the end of .map like this:

return aInts.map { aInt in
    do {
        try ADouble.convert(aInt)
    }
    catch {
        print(error)
    }
    return ADouble(aDouble: 2.2)
}

Error disappear, but when i print try b.doAction(aInts) on same aInts array, i get this: [ADouble(aDouble: 2.2), ADouble(aDouble: 2.2)], i.e. it prints my ADouble(aDouble: 2.2) that i set manually. Obviously, it's not what i want, so then i try to add return before try ADouble.convert(aInt) like this:

return aInts.map { aInt in
    do {
        return try ADouble.convert(aInt)
    }
    catch {
        print(error)
    }
    return ADouble(aDouble: 2.2)
}

And now i get right result: [ADouble(aDouble: 2.0), ADouble(aDouble: 3.0)]. But this code still doesn't work without return statement in the end of the .map. Any ideas how to get rid of it?

Upvotes: 2

Views: 2972

Answers (1)

Martin R
Martin R

Reputation: 539685

The map() method is declared as

@rethrows public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]

which means (if I understand it correctly) that the transform can either return a value or throw an error (and this will be forwarded to the caller).

This compiles and works as expected:

struct B {
    func doAction(aInts: [AInt]) throws -> [ADouble] {
        return try aInts.map { aInt in 
            return try ADouble.convert(aInt)
        }
    }
}

An error thrown from ADouble.convert(aInt) will be forwarded to the caller of map() and from there to the caller of doAction().

Upvotes: 1

Related Questions